From 08a2f8aec1acb973d6dc89516487a8bc53257605 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 23 May 2017 00:04:03 +0100 Subject: [PATCH 001/129] Fix constant propagator. --- src/analyses/constant_propagator.cpp | 481 +++++++++++++++------------ src/analyses/constant_propagator.h | 118 ++++--- src/analyses/replace_symbol_ext.cpp | 20 +- 3 files changed, 347 insertions(+), 272 deletions(-) diff --git a/src/analyses/constant_propagator.cpp b/src/analyses/constant_propagator.cpp index 15cda33e864..d3fc588b9dc 100644 --- a/src/analyses/constant_propagator.cpp +++ b/src/analyses/constant_propagator.cpp @@ -19,106 +19,25 @@ Author: Peter Schrammel #include "constant_propagator.h" -exprt concatenate_array_id( - const exprt &array, const exprt &index, - const typet &type) -{ - std::string a, idx, identifier; - a = array.get_string(ID_identifier); - - if (index.id()==ID_typecast) - idx = index.op0().get_string(ID_value); - else - idx = index.get_string(ID_value); - - mp_integer i=string2integer(idx); - identifier=a+"["+integer2string(i)+"]"; - symbol_exprt new_expr(identifier, type); - - return new_expr; -} - -exprt concatenate_array_id( - const exprt &array, const mp_integer &index, - const typet &type) -{ - std::string a, identifier; - a = array.get_string(ID_identifier); - identifier=a+"["+integer2string(index)+"]"; - symbol_exprt new_expr(identifier, type); - - return new_expr; -} - void constant_propagator_domaint::assign_rec( valuest &values, - const exprt &lhs, const exprt &rhs, + const exprt &lhs, + const exprt &rhs, const namespacet &ns) { - const typet & lhs_type = ns.follow(lhs.type()); - const typet & rhs_type = ns.follow(rhs.type()); + if(lhs.id()!=ID_symbol) + return; -#ifdef DEBUG - std::cout << "assign: " << from_expr(ns, "", lhs) - << " := " << from_type(ns, "", rhs_type) << '\n'; -#endif + const symbol_exprt &s=to_symbol_expr(lhs); - if(lhs.id()==ID_symbol && rhs.id()==ID_if) - { - exprt cond=rhs.op0(); - assert(cond.operands().size()==2); - if(values.is_constant(cond.op0()) - && values.is_constant(cond.op1())) - { - if(cond.op0().id()==ID_index) - { - exprt index=cond.op0(); - exprt new_expr=concatenate_array_id(index.op0(), index.op1(), index.type()); - values.replace_const(new_expr); - cond.op0()=new_expr; - cond = simplify_expr(cond,ns); - } - else - assert(0); + exprt tmp=rhs; + values.replace_const(tmp); + tmp=simplify_expr(tmp, ns); - assign(values, to_symbol_expr(lhs), cond, ns); - } - } - else if(lhs.id()==ID_symbol && rhs_type.id()!=ID_array - && rhs_type.id()!=ID_struct - && rhs_type.id()!=ID_union) - { - if(values.is_constant(rhs)) - assign(values, to_symbol_expr(lhs), rhs, ns); - else - values.set_to_top(to_symbol_expr(lhs)); - } - else if(lhs.id()==ID_symbol && lhs_type.id()==ID_array - && rhs_type.id()==ID_array) - { - exprt new_expr; - mp_integer idx=0; - forall_operands(it, rhs) - { - new_expr=concatenate_array_id(lhs, idx, it->type()); - assign(values, to_symbol_expr(new_expr), *it, ns); - idx = idx +1; - } - } - else if (lhs.id()==ID_index) - { - if (values.is_constant(lhs.op1()) - && values.is_constant(rhs)) - { - exprt new_expr=concatenate_array_id(lhs.op0(), lhs.op1(), rhs.type()); - assign(values, to_symbol_expr(new_expr), rhs, ns); - } - } -#if 0 - else // TODO: could make field or array element-sensitive - { - } -#endif + if(tmp.is_constant()) + values.set_to(s, tmp); + else + values.set_to_top(s); } void constant_propagator_domaint::transform( @@ -127,16 +46,24 @@ void constant_propagator_domaint::transform( ai_baset &ai, const namespacet &ns) { - #ifdef DEBUG +#ifdef DEBUG + std::cout << "Transform from/to:\n"; std::cout << from->location_number << " --> " << to->location_number << '\n'; - #endif +#endif #ifdef DEBUG - std::cout << "before:\n"; + std::cout << "Before:\n"; output(std::cout, ai, ns); #endif + const constant_propagator_ait *cp= + dynamic_cast(&ai); + bool have_dirty=(cp!=nullptr); + + if(values.is_bottom) + return; + if(from->is_decl()) { const code_declt &code_decl=to_code_decl(from->code); @@ -146,8 +73,8 @@ void constant_propagator_domaint::transform( else if(from->is_assign()) { const code_assignt &assignment=to_code_assign(from->code); - const exprt &lhs = assignment.lhs(); - const exprt &rhs = assignment.rhs(); + const exprt &lhs=assignment.lhs(); + const exprt &rhs=assignment.rhs(); assign_rec(values, lhs, rhs, ns); } else if(from->is_assume()) @@ -159,19 +86,15 @@ void constant_propagator_domaint::transform( exprt g; if(from->get_target()==to) - g = simplify_expr(from->guard, ns); + g=simplify_expr(from->guard, ns); else - g = simplify_expr(not_exprt(from->guard), ns); + g=simplify_expr(not_exprt(from->guard), ns); - if (g.is_false()) + if(g.is_false()) values.set_to_bottom(); else { - //TODO: we need to support widening! - if (g.is_constant()) - values.set_to_top(); - else - two_way_propagate_rec(g, ns); + two_way_propagate_rec(g, ns); } } else if(from->is_dead()) @@ -181,30 +104,98 @@ void constant_propagator_domaint::transform( } else if(from->is_function_call()) { - const exprt &function=to_code_function_call(from->code).function(); + const code_function_callt &function_call=to_code_function_call(from->code); + const exprt &function=function_call.function(); + + locationt next=from; + next++; if(function.id()==ID_symbol) { - const irep_idt &identifier=to_symbol_expr(function).get_identifier(); - - if(identifier=="__CPROVER_set_must" || - identifier=="__CPROVER_get_must" || - identifier=="__CPROVER_set_may" || - identifier=="__CPROVER_get_may" || - identifier=="__CPROVER_cleanup" || - identifier=="__CPROVER_clear_may" || - identifier=="__CPROVER_clear_must") + // called function identifier + const symbol_exprt &symbol_expr=to_symbol_expr(function); + const irep_idt id=symbol_expr.get_identifier(); + + if(to==next) { + if(id=="__CPROVER_set_must" || + id=="__CPROVER_get_must" || + id=="__CPROVER_set_may" || + id=="__CPROVER_get_may" || + id=="__CPROVER_cleanup" || + id=="__CPROVER_clear_may" || + id=="__CPROVER_clear_must") + { + // no effect on constants + } + else + { + if(have_dirty) + values.set_dirty_to_top(cp->dirty, ns); + else + values.set_to_top(); + } } else - values.set_to_top(); + { + // we have an actual call + + // parameters of called function + const symbolt &symbol=ns.lookup(id); + const code_typet &code_type=to_code_type(symbol.type); + const code_typet::parameterst ¶meters=code_type.parameters(); + + const code_function_callt::argumentst &arguments + =function_call.arguments(); + + unsigned n=std::min(arguments.size(), parameters.size()); + + for(unsigned i=0; idirty, ns); + else + values.set_to_top(); + } + } + else if(from->is_end_function()) + { + // erase parameters + + const irep_idt id=from->function; + const symbolt &symbol=ns.lookup(id); + + const code_typet &type=to_code_type(symbol.type); + + typedef code_typet::parameterst parameterst; + const parameterst ¶meters=type.parameters(); + + for(parameterst::const_iterator it=parameters.begin(); + it!=parameters.end(); it++) + { + // normal parameter + const irep_idt par=it->get_identifier(); + + // this erases the parameter from the map + values.set_to_top(par); + } } #ifdef DEBUG - std::cout << "after:\n"; + std::cout << "After:\n"; output(std::cout, ai, ns); #endif } @@ -218,7 +209,8 @@ bool constant_propagator_domaint::two_way_propagate_rec( #ifdef DEBUG std::cout << "two_way_propagate_rec: " << from_expr(ns, "", expr) << '\n'; #endif - bool change = false; + + bool change=false; if(expr.id()==ID_and) { @@ -235,32 +227,22 @@ bool constant_propagator_domaint::two_way_propagate_rec( } else if(expr.id()==ID_equal) { - const exprt &lhs = expr.op0(); - const exprt &rhs = expr.op1(); + const exprt &lhs=expr.op0(); + const exprt &rhs=expr.op1(); // two-way propagation valuest copy_values = values; assign_rec(copy_values, lhs, rhs, ns); if(!values.is_constant(rhs) || values.is_constant(lhs)) - assign_rec(values, rhs, lhs, ns); + assign_rec(values, rhs, lhs, ns); change = values.meet(copy_values); } #ifdef DEBUG std::cout << "two_way_propagate_rec: " << change << '\n'; #endif - return change; -} -void constant_propagator_domaint::assign( - valuest &dest, - const symbol_exprt &lhs, - exprt rhs, - const namespacet &ns) const -{ - values.replace_const(rhs); - rhs = simplify_expr(rhs, ns); - dest.set_to(lhs, rhs); + return change; } /// Simplify the condition given context-sensitive knowledge from the abstract @@ -277,17 +259,6 @@ bool constant_propagator_domaint::ai_simplify( return b; } -bool constant_propagator_domaint::valuest::is_array_constant(const exprt &expr) const -{ - exprt new_expr = concatenate_array_id(expr.op0(), - expr.op1(), expr.type()); - - if (replace_const.expr_map.find(to_symbol_expr(new_expr).get_identifier()) == - replace_const.expr_map.end()) - return false; - - return true; -} bool constant_propagator_domaint::valuest::is_constant(const exprt &expr) const { @@ -300,12 +271,12 @@ bool constant_propagator_domaint::valuest::is_constant(const exprt &expr) const return false; if(expr.id()==ID_symbol) - if(replace_const.expr_map.find(to_symbol_expr(expr).get_identifier()) == + if(replace_const.expr_map.find(to_symbol_expr(expr).get_identifier())== replace_const.expr_map.end()) return false; - if (expr.id()==ID_index) - return is_array_constant(expr); + if(expr.id()==ID_index) + return false; if(expr.id()==ID_address_of) return is_constant_address_of(to_address_of_expr(expr).object()); @@ -339,19 +310,51 @@ bool constant_propagator_domaint::valuest::is_constant_address_of( /// Do not call this when iterating over replace_const.expr_map! bool constant_propagator_domaint::valuest::set_to_top(const irep_idt &id) { - bool result = false; - - replace_symbolt::expr_mapt::iterator r_it = - replace_const.expr_map.find(id); + replace_symbolt::expr_mapt::iterator r_it + =replace_const.expr_map.find(id); - if(r_it != replace_const.expr_map.end()) + if(r_it!=replace_const.expr_map.end()) { assert(!is_bottom); replace_const.expr_map.erase(r_it); - result = true; + return true; } - return result; + return false; +} + +/*******************************************************************\ + +Function: constant_propagator_domaint::valuest::set_dirty_to_top + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void constant_propagator_domaint::valuest::set_dirty_to_top( + const dirtyt &dirty, + const namespacet &ns) +{ + typedef replace_symbol_extt::expr_mapt expr_mapt; + expr_mapt &expr_map=replace_const.expr_map; + + for(expr_mapt::iterator it=expr_map.begin(); + it!=expr_map.end();) + { + const irep_idt id=it->first; + + const symbolt &symbol=ns.lookup(id); + + if((!symbol.is_procedure_local() || dirty(id)) && + !symbol.type.get_bool(ID_C_constant)) + it=expr_map.erase(it); + else + it++; + } } void constant_propagator_domaint::valuest::output( @@ -361,11 +364,26 @@ void constant_propagator_domaint::valuest::output( out << "const map:\n"; if(is_bottom) + { out << " bottom\n"; + assert(replace_const.expr_map.empty()); + return; + } + + assert(!is_bottom); + if(replace_const.expr_map.empty()) + { + out << "top\n"; + return; + } - for(const auto &replace_pair : replace_const.expr_map) - out << ' ' << replace_pair.first << "=" - << from_expr(ns, "", replace_pair.second) << '\n'; + for(replace_symbolt::expr_mapt::const_iterator + it=replace_const.expr_map.begin(); + it!=replace_const.expr_map.end(); + ++it) + { + out << ' ' << it->first << "=" << from_expr(ns, "", it->second) << '\n'; + } } void constant_propagator_domaint::output( @@ -380,6 +398,10 @@ void constant_propagator_domaint::output( /// \return Return true if "this" has changed. bool constant_propagator_domaint::valuest::merge(const valuest &src) { + // dummy + const symbol_tablet symbol_table; + const namespacet ns(symbol_table); + // nothing to do if(src.is_bottom) return false; @@ -387,38 +409,64 @@ bool constant_propagator_domaint::valuest::merge(const valuest &src) // just copy if(is_bottom) { - replace_const = src.replace_const; - is_bottom = src.is_bottom; + assert(!src.is_bottom); + replace_const=src.replace_const; // copy + is_bottom=false; return true; } - bool changed = false; + assert(!is_bottom && !src.is_bottom); - // set everything to top that is not in src - for(replace_symbolt::expr_mapt::const_iterator - it=replace_const.expr_map.begin(); - it!=replace_const.expr_map.end(); - ) // no it++ + bool changed=false; + + replace_symbol_extt::expr_mapt &expr_map=replace_const.expr_map; + const replace_symbol_extt::expr_mapt &src_expr_map=src.replace_const.expr_map; + + // handle top + if(src_expr_map.empty()) + { + // change if it was not top + changed=!expr_map.empty(); + + set_to_top(); + assert(expr_map.empty()); + assert(!is_bottom); + + return changed; + } + + // remove those that are + // - different in src + // - do not exist in src + for(replace_symbolt::expr_mapt::iterator it=expr_map.begin(); + it!=expr_map.end();) { - const replace_symbolt::expr_mapt::const_iterator - b_it=src.replace_const.expr_map.find(it->first); + const irep_idt id=it->first; + const exprt &expr=it->second; - if(b_it==src.replace_const.expr_map.end()) + replace_symbolt::expr_mapt::const_iterator s_it; + s_it=src_expr_map.find(id); + + if(s_it!=src_expr_map.end()) { - //cannot use set_to_top here - replace_const.expr_map.erase(it); - changed = true; - break; + // check value + const exprt &src_expr=s_it->second; + + if(expr!=src_expr) + { + it=expr_map.erase(it); + changed=true; + } + else + it++; } else { - const exprt previous=it->second; - replace_const.expr_map[b_it->first]=b_it->second; - if (it->second != previous) changed = true; - - it++; + it=expr_map.erase(it); + changed=true; } } + return changed; } @@ -431,24 +479,27 @@ bool constant_propagator_domaint::valuest::meet(const valuest &src) bool changed = false; - for(const auto &src_replace_pair : src.replace_const.expr_map) + for(replace_symbolt::expr_mapt::const_iterator + it=src.replace_const.expr_map.begin(); + it!=src.replace_const.expr_map.end(); + ++it) { - replace_symbolt::expr_mapt::iterator c_it= - replace_const.expr_map.find(src_replace_pair.first); + replace_symbolt::expr_mapt::iterator + c_it = replace_const.expr_map.find(it->first); if(c_it!=replace_const.expr_map.end()) { - if(c_it->second!=src_replace_pair.second) + if(c_it->second!=it->second) { set_to_bottom(); - changed=true; + changed = true; break; } } else { - set_to(src_replace_pair.first, src_replace_pair.second); - changed=true; + set_to(it->first, it->second); + changed = true; } } @@ -461,7 +512,31 @@ bool constant_propagator_domaint::merge( locationt from, locationt to) { - return values.merge(other.values); + const symbol_tablet symbol_table; + const namespacet ns(symbol_table); + +#if 0 + if(to->is_skip()) + { + std::cout << "This:\n"; + values.output(std::cout, ns); + std::cout << "Other:\n"; + other.values.output(std::cout, ns); + } +#endif + + bool b; + b=values.merge(other.values); + +#if 0 + if(to->is_skip()) + { + std::cout << "Merge result:\n"; + values.output(std::cout, ns); + } +#endif + + return b; } void constant_propagator_ait::replace( @@ -472,21 +547,6 @@ void constant_propagator_ait::replace( replace(f_it->second, ns); } -void constant_propagator_ait::replace_array_symbol(exprt &expr) -{ - if (expr.id()==ID_index) - expr = concatenate_array_id(expr.op0(), - expr.op1(), expr.type()); - - Forall_operands(it, expr) - { - if (it->id()==ID_equal) - replace_array_symbol(it->op0()); - else if (it->id()==ID_index) - replace_array_symbol(expr.op0()); - } - -} void constant_propagator_ait::replace( goto_functionst::goto_functiont &goto_function, @@ -494,9 +554,9 @@ void constant_propagator_ait::replace( { Forall_goto_program_instructions(it, goto_function.body) { - state_mapt::iterator s_it = state_map.find(it); + state_mapt::iterator s_it=state_map.find(it); - if(s_it == state_map.end()) + if(s_it==state_map.end()) continue; replace_types_rec(s_it->second.values.replace_const, it->code); @@ -504,16 +564,15 @@ void constant_propagator_ait::replace( if(it->is_goto() || it->is_assume() || it->is_assert()) { - replace_array_symbol(it->guard); s_it->second.values.replace_const(it->guard); it->guard = simplify_expr(it->guard, ns); } else if(it->is_assign()) { - exprt &rhs = to_code_assign(it->code).rhs(); + exprt &rhs=to_code_assign(it->code).rhs(); s_it->second.values.replace_const(rhs); - rhs = simplify_expr(rhs, ns); - if (rhs.id()==ID_constant) + rhs=simplify_expr(rhs, ns); + if(rhs.id()==ID_constant) rhs.add_source_location()=it->code.op0().source_location(); } else if(it->is_function_call()) @@ -522,14 +581,14 @@ void constant_propagator_ait::replace( to_code_function_call(it->code).function()); simplify_expr(to_code_function_call(it->code).function(), ns); - exprt::operandst &args = + exprt::operandst &args= to_code_function_call(it->code).arguments(); - for(exprt::operandst::iterator o_it = args.begin(); - o_it != args.end(); ++o_it) + for(exprt::operandst::iterator o_it=args.begin(); + o_it!=args.end(); ++o_it) { s_it->second.values.replace_const(*o_it); - *o_it = simplify_expr(*o_it, ns); + *o_it=simplify_expr(*o_it, ns); } } else if(it->is_other()) diff --git a/src/analyses/constant_propagator.h b/src/analyses/constant_propagator.h index 0b54c79bdb8..3193ef9c4f3 100644 --- a/src/analyses/constant_propagator.h +++ b/src/analyses/constant_propagator.h @@ -12,93 +12,118 @@ Author: Peter Schrammel #ifndef CPROVER_ANALYSES_CONSTANT_PROPAGATOR_H #define CPROVER_ANALYSES_CONSTANT_PROPAGATOR_H +#include + #include "ai.h" +#include "dirty.h" #include "replace_symbol_ext.h" class constant_propagator_domaint:public ai_domain_baset { public: - void transform( - locationt, - locationt, - ai_baset &, - const namespacet &) final; - void output( - std::ostream &, - const ai_baset &, - const namespacet &) const final; - void make_top() final { values.set_to_top(); } - void make_bottom() final { values.set_to_bottom(); } - void make_entry() final { values.set_to_top(); } - bool merge(const constant_propagator_domaint &, locationt, locationt); + virtual void transform( + locationt from, + locationt to, + ai_baset &ai_base, + const namespacet &ns); + + virtual void output( + std::ostream &out, + const ai_baset &ai_base, + const namespacet &ns) const; + + bool merge( + const constant_propagator_domaint &other, + locationt from, + locationt to); virtual bool ai_simplify( exprt &condition, const namespacet &ns) const override; + virtual void make_bottom() + { + values.set_to_bottom(); + } + + virtual void make_top() + { + values.set_to_top(); + } + + virtual void make_entry() + { + make_top(); + } + struct valuest { public: - valuest():is_bottom(true) { } + valuest():is_bottom(true) {} // maps variables to constants replace_symbol_extt replace_const; bool is_bottom; - void output(std::ostream &, const namespacet &) const; - bool merge(const valuest &src); bool meet(const valuest &src); - void set_to_bottom() + // set whole state + + inline void set_to_bottom() { replace_const.clear(); - is_bottom = true; + is_bottom=true; } - void set_to(const irep_idt &lhs_id, const exprt &rhs_val) + inline void set_to_top() { - replace_const.expr_map[lhs_id] = rhs_val; - is_bottom = false; + replace_const.clear(); + is_bottom=false; } - void set_to(const symbol_exprt &lhs, const exprt &rhs_val) + // set single identifier + + inline void set_to(const irep_idt &lhs, const exprt &rhs) { - set_to(lhs.get_identifier(), rhs_val); + replace_const.expr_map[lhs]=rhs; + is_bottom=false; } - bool is_constant(const exprt &expr) const; - bool is_array_constant(const exprt &expr) const; - bool is_constant_address_of(const exprt &expr) const; - bool set_to_top(const irep_idt &id); + inline void set_to(const symbol_exprt &lhs, const exprt &rhs) + { + set_to(lhs.get_identifier(), rhs); + } bool set_to_top(const symbol_exprt &expr) { return set_to_top(expr.get_identifier()); } - void set_to_top() + bool set_to_top(const irep_idt &id); + + void set_dirty_to_top(const dirtyt &dirty, const namespacet &ns); + + bool is_constant(const exprt &expr) const; + bool is_array_constant(const exprt &expr) const; + bool is_constant_address_of(const exprt &expr) const; + + bool is_empty() const { - replace_const.clear(); - is_bottom = false; + assert(replace_const.type_map.empty()); + return replace_const.expr_map.empty(); } + void output(std::ostream &out, const namespacet &ns) const; }; valuest values; -private: - void assign( - valuest &dest, - const symbol_exprt &lhs, - exprt rhs, - const namespacet &ns) const; - +protected: void assign_rec( valuest &values, - const exprt &lhs, - const exprt &rhs, + const exprt &lhs, const exprt &rhs, const namespacet &ns); bool two_way_propagate_rec( @@ -109,9 +134,14 @@ class constant_propagator_domaint:public ai_domain_baset class constant_propagator_ait:public ait { public: + explicit constant_propagator_ait(const goto_functionst &goto_functions): + dirty(goto_functions) + { + } + constant_propagator_ait( goto_functionst &goto_functions, - const namespacet &ns) + const namespacet &ns):dirty(goto_functions) { operator()(goto_functions, ns); replace(goto_functions, ns); @@ -119,18 +149,17 @@ class constant_propagator_ait:public ait constant_propagator_ait( goto_functionst::goto_functiont &goto_function, - const namespacet &ns) + const namespacet &ns):dirty(goto_function) { operator()(goto_function, ns); replace(goto_function, ns); } + dirtyt dirty; + protected: friend class constant_propagator_domaint; - void replace_array_symbol( - exprt &expr); - void replace( goto_functionst::goto_functiont &, const namespacet &); @@ -142,7 +171,6 @@ class constant_propagator_ait:public ait void replace_types_rec( const replace_symbolt &replace_const, exprt &expr); - }; #endif // CPROVER_ANALYSES_CONSTANT_PROPAGATOR_H diff --git a/src/analyses/replace_symbol_ext.cpp b/src/analyses/replace_symbol_ext.cpp index 75c697030b7..460fdb752d2 100644 --- a/src/analyses/replace_symbol_ext.cpp +++ b/src/analyses/replace_symbol_ext.cpp @@ -17,7 +17,7 @@ Author: Peter Schrammel /// does not replace object in address_of expressions bool replace_symbol_extt::replace(exprt &dest) const { - bool result=true; + bool result=true; // nothing changed // first look at type @@ -30,20 +30,7 @@ bool replace_symbol_extt::replace(exprt &dest) const if(!have_to_replace(dest)) return result; - // do not replace object in address_of expressions - if(dest.id()==ID_address_of) - { - const exprt &object = to_address_of_expr(dest).object(); - if(object.id()==ID_symbol) - { - expr_mapt::const_iterator it= - expr_map.find(object.get(ID_identifier)); - - if(it!=expr_map.end()) - return false; - } - } - else if(dest.id()==ID_symbol) + if(dest.id()==ID_symbol) { expr_mapt::const_iterator it= expr_map.find(dest.get(ID_identifier)); @@ -69,7 +56,8 @@ bool replace_symbol_extt::replace(exprt &dest) const const irept &va_arg_type=dest.find(ID_C_va_arg_type); if(va_arg_type.is_not_nil() && - !replace_symbolt::replace(static_cast(dest.add(ID_C_va_arg_type)))) + !replace_symbolt::replace( + static_cast(dest.add(ID_C_va_arg_type)))) result=false; return result; From 956225f4aa6ac679335ca862c9dabccd0f50728b Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Mon, 30 Jan 2017 18:29:21 +0000 Subject: [PATCH 002/129] disable two-way propagation for now --- src/analyses/constant_propagator.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/analyses/constant_propagator.cpp b/src/analyses/constant_propagator.cpp index d3fc588b9dc..35a82831826 100644 --- a/src/analyses/constant_propagator.cpp +++ b/src/analyses/constant_propagator.cpp @@ -61,8 +61,7 @@ void constant_propagator_domaint::transform( dynamic_cast(&ai); bool have_dirty=(cp!=nullptr); - if(values.is_bottom) - return; + assert(!values.is_bottom); if(from->is_decl()) { @@ -95,6 +94,8 @@ void constant_propagator_domaint::transform( else { two_way_propagate_rec(g, ns); + assert(!values.is_bottom); // for now + // While two-way propagation is disabled this should be impossible. } } else if(from->is_dead()) @@ -194,6 +195,8 @@ void constant_propagator_domaint::transform( } } + assert(from->is_goto() || !values.is_bottom); + #ifdef DEBUG std::cout << "After:\n"; output(std::cout, ai, ns); @@ -212,6 +215,7 @@ bool constant_propagator_domaint::two_way_propagate_rec( bool change=false; +#if 0 if(expr.id()==ID_and) { // need a fixed point here to get the most out of it @@ -221,7 +225,7 @@ bool constant_propagator_domaint::two_way_propagate_rec( forall_operands(it, expr) if(two_way_propagate_rec(*it, ns)) - change = true; + change=true; } while(change); } @@ -231,12 +235,13 @@ bool constant_propagator_domaint::two_way_propagate_rec( const exprt &rhs=expr.op1(); // two-way propagation - valuest copy_values = values; + valuest copy_values=values; assign_rec(copy_values, lhs, rhs, ns); if(!values.is_constant(rhs) || values.is_constant(lhs)) assign_rec(values, rhs, lhs, ns); - change = values.meet(copy_values); + change=values.meet(copy_values); } +#endif #ifdef DEBUG std::cout << "two_way_propagate_rec: " << change << '\n'; From 1b131145afe3cf8ecc7a62678a60e1e81f5c0a9f Mon Sep 17 00:00:00 2001 From: martin Date: Wed, 24 May 2017 17:49:39 +0100 Subject: [PATCH 003/129] Addressing constant domain review comments by Daniel Poetzl. --- src/analyses/Makefile | 1 - src/analyses/constant_propagator.cpp | 136 +++++++++------------------ src/analyses/constant_propagator.h | 11 ++- src/analyses/replace_symbol_ext.cpp | 64 ------------- src/analyses/replace_symbol_ext.h | 23 ----- src/util/replace_symbol.cpp | 74 ++++++++++++--- src/util/replace_symbol.h | 16 +++- 7 files changed, 126 insertions(+), 199 deletions(-) delete mode 100644 src/analyses/replace_symbol_ext.cpp delete mode 100644 src/analyses/replace_symbol_ext.h diff --git a/src/analyses/Makefile b/src/analyses/Makefile index 690b119e83c..9be0609687f 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -22,7 +22,6 @@ SRC = ai.cpp \ locals.cpp \ natural_loops.cpp \ reaching_definitions.cpp \ - replace_symbol_ext.cpp \ static_analysis.cpp \ uninitialized_domain.cpp \ # Empty last line diff --git a/src/analyses/constant_propagator.cpp b/src/analyses/constant_propagator.cpp index 35a82831826..3e6f9d41b17 100644 --- a/src/analyses/constant_propagator.cpp +++ b/src/analyses/constant_propagator.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ -Module: Constant Propagation +Module: Constant propagation Author: Peter Schrammel @@ -16,6 +16,7 @@ Author: Peter Schrammel #include #include #include +#include #include "constant_propagator.h" @@ -32,7 +33,7 @@ void constant_propagator_domaint::assign_rec( exprt tmp=rhs; values.replace_const(tmp); - tmp=simplify_expr(tmp, ns); + simplify(tmp, ns); if(tmp.is_constant()) values.set_to(s, tmp); @@ -119,13 +120,13 @@ void constant_propagator_domaint::transform( if(to==next) { - if(id=="__CPROVER_set_must" || - id=="__CPROVER_get_must" || - id=="__CPROVER_set_may" || - id=="__CPROVER_get_may" || - id=="__CPROVER_cleanup" || - id=="__CPROVER_clear_may" || - id=="__CPROVER_clear_must") + if(id==CPROVER_PREFIX "set_must" || + id==CPROVER_PREFIX "get_must" || + id==CPROVER_PREFIX "set_may" || + id==CPROVER_PREFIX "get_may" || + id==CPROVER_PREFIX "cleanup" || + id==CPROVER_PREFIX "clear_may" || + id==CPROVER_PREFIX "clear_must") { // no effect on constants } @@ -146,17 +147,19 @@ void constant_propagator_domaint::transform( const code_typet &code_type=to_code_type(symbol.type); const code_typet::parameterst ¶meters=code_type.parameters(); - const code_function_callt::argumentst &arguments - =function_call.arguments(); + const code_function_callt::argumentst &arguments= + function_call.arguments(); - unsigned n=std::min(arguments.size(), parameters.size()); - - for(unsigned i=0; iget_identifier(), arg.type()); + assign_rec(values, parameter_expr, arg, ns); - assign_rec(values, parameter_expr, arguments[i], ns); + ++p_it; } } } @@ -181,18 +184,8 @@ void constant_propagator_domaint::transform( const code_typet &type=to_code_type(symbol.type); - typedef code_typet::parameterst parameterst; - const parameterst ¶meters=type.parameters(); - - for(parameterst::const_iterator it=parameters.begin(); - it!=parameters.end(); it++) - { - // normal parameter - const irep_idt par=it->get_identifier(); - - // this erases the parameter from the map - values.set_to_top(par); - } + for(const auto ¶m : type.parameters()) + values.set_to_top(param.get_identifier()); } assert(from->is_goto() || !values.is_bottom); @@ -215,6 +208,7 @@ bool constant_propagator_domaint::two_way_propagate_rec( bool change=false; + // this seems to be buggy at present #if 0 if(expr.id()==ID_and) { @@ -315,17 +309,12 @@ bool constant_propagator_domaint::valuest::is_constant_address_of( /// Do not call this when iterating over replace_const.expr_map! bool constant_propagator_domaint::valuest::set_to_top(const irep_idt &id) { - replace_symbolt::expr_mapt::iterator r_it - =replace_const.expr_map.find(id); + replace_symbolt::expr_mapt::size_type n_erased= + replace_const.expr_map.erase(id); - if(r_it!=replace_const.expr_map.end()) - { - assert(!is_bottom); - replace_const.expr_map.erase(r_it); - return true; - } + assert(n_erased==0 || !is_bottom); - return false; + return n_erased>0; } /*******************************************************************\ @@ -344,7 +333,7 @@ void constant_propagator_domaint::valuest::set_dirty_to_top( const dirtyt &dirty, const namespacet &ns) { - typedef replace_symbol_extt::expr_mapt expr_mapt; + typedef replace_symbolt::expr_mapt expr_mapt; expr_mapt &expr_map=replace_const.expr_map; for(expr_mapt::iterator it=expr_map.begin(); @@ -382,12 +371,9 @@ void constant_propagator_domaint::valuest::output( return; } - for(replace_symbolt::expr_mapt::const_iterator - it=replace_const.expr_map.begin(); - it!=replace_const.expr_map.end(); - ++it) + for(const auto &p : replace_const.expr_map) { - out << ' ' << it->first << "=" << from_expr(ns, "", it->second) << '\n'; + out << ' ' << p.first << "=" << from_expr(ns, "", p.second) << '\n'; } } @@ -403,10 +389,6 @@ void constant_propagator_domaint::output( /// \return Return true if "this" has changed. bool constant_propagator_domaint::valuest::merge(const valuest &src) { - // dummy - const symbol_tablet symbol_table; - const namespacet ns(symbol_table); - // nothing to do if(src.is_bottom) return false; @@ -424,8 +406,8 @@ bool constant_propagator_domaint::valuest::merge(const valuest &src) bool changed=false; - replace_symbol_extt::expr_mapt &expr_map=replace_const.expr_map; - const replace_symbol_extt::expr_mapt &src_expr_map=src.replace_const.expr_map; + replace_symbolt::expr_mapt &expr_map=replace_const.expr_map; + const replace_symbolt::expr_mapt &src_expr_map=src.replace_const.expr_map; // handle top if(src_expr_map.empty()) @@ -434,8 +416,6 @@ bool constant_propagator_domaint::valuest::merge(const valuest &src) changed=!expr_map.empty(); set_to_top(); - assert(expr_map.empty()); - assert(!is_bottom); return changed; } @@ -482,29 +462,26 @@ bool constant_propagator_domaint::valuest::meet(const valuest &src) if(src.is_bottom || is_bottom) return false; - bool changed = false; + bool changed=false; - for(replace_symbolt::expr_mapt::const_iterator - it=src.replace_const.expr_map.begin(); - it!=src.replace_const.expr_map.end(); - ++it) + for(const auto &m : src.replace_const.expr_map) { replace_symbolt::expr_mapt::iterator - c_it = replace_const.expr_map.find(it->first); + c_it=replace_const.expr_map.find(m.first); if(c_it!=replace_const.expr_map.end()) { - if(c_it->second!=it->second) + if(c_it->second!=m.second) { set_to_bottom(); - changed = true; + changed=true; break; } } else { - set_to(it->first, it->second); - changed = true; + set_to(m.first, m.second); + changed=true; } } @@ -517,31 +494,7 @@ bool constant_propagator_domaint::merge( locationt from, locationt to) { - const symbol_tablet symbol_table; - const namespacet ns(symbol_table); - -#if 0 - if(to->is_skip()) - { - std::cout << "This:\n"; - values.output(std::cout, ns); - std::cout << "Other:\n"; - other.values.output(std::cout, ns); - } -#endif - - bool b; - b=values.merge(other.values); - -#if 0 - if(to->is_skip()) - { - std::cout << "Merge result:\n"; - values.output(std::cout, ns); - } -#endif - - return b; + return values.merge(other.values); } void constant_propagator_ait::replace( @@ -570,13 +523,13 @@ void constant_propagator_ait::replace( if(it->is_goto() || it->is_assume() || it->is_assert()) { s_it->second.values.replace_const(it->guard); - it->guard = simplify_expr(it->guard, ns); + simplify(it->guard, ns); } else if(it->is_assign()) { exprt &rhs=to_code_assign(it->code).rhs(); s_it->second.values.replace_const(rhs); - rhs=simplify_expr(rhs, ns); + simplify(rhs, ns); if(rhs.id()==ID_constant) rhs.add_source_location()=it->code.op0().source_location(); } @@ -584,7 +537,8 @@ void constant_propagator_ait::replace( { s_it->second.values.replace_const( to_code_function_call(it->code).function()); - simplify_expr(to_code_function_call(it->code).function(), ns); + + simplify(to_code_function_call(it->code).function(), ns); exprt::operandst &args= to_code_function_call(it->code).arguments(); @@ -593,7 +547,7 @@ void constant_propagator_ait::replace( o_it!=args.end(); ++o_it) { s_it->second.values.replace_const(*o_it); - *o_it=simplify_expr(*o_it, ns); + simplify(*o_it, ns); } } else if(it->is_other()) diff --git a/src/analyses/constant_propagator.h b/src/analyses/constant_propagator.h index 3193ef9c4f3..437c7744ff8 100644 --- a/src/analyses/constant_propagator.h +++ b/src/analyses/constant_propagator.h @@ -12,13 +12,12 @@ Author: Peter Schrammel #ifndef CPROVER_ANALYSES_CONSTANT_PROPAGATOR_H #define CPROVER_ANALYSES_CONSTANT_PROPAGATOR_H -#include +#include +#include #include "ai.h" #include "dirty.h" -#include "replace_symbol_ext.h" - class constant_propagator_domaint:public ai_domain_baset { public: @@ -63,7 +62,7 @@ class constant_propagator_domaint:public ai_domain_baset valuest():is_bottom(true) {} // maps variables to constants - replace_symbol_extt replace_const; + replace_symbolt replace_const; bool is_bottom; bool merge(const valuest &src); @@ -143,6 +142,8 @@ class constant_propagator_ait:public ait goto_functionst &goto_functions, const namespacet &ns):dirty(goto_functions) { + assert(false); + operator()(goto_functions, ns); replace(goto_functions, ns); } @@ -151,6 +152,8 @@ class constant_propagator_ait:public ait goto_functionst::goto_functiont &goto_function, const namespacet &ns):dirty(goto_function) { + assert(false); + operator()(goto_function, ns); replace(goto_function, ns); } diff --git a/src/analyses/replace_symbol_ext.cpp b/src/analyses/replace_symbol_ext.cpp deleted file mode 100644 index 460fdb752d2..00000000000 --- a/src/analyses/replace_symbol_ext.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/*******************************************************************\ - -Module: Modified expression replacement for constant propagator - -Author: Peter Schrammel - -\*******************************************************************/ - -/// \file -/// Modified expression replacement for constant propagator - -#include -#include - -#include "replace_symbol_ext.h" - -/// does not replace object in address_of expressions -bool replace_symbol_extt::replace(exprt &dest) const -{ - bool result=true; // nothing changed - - // first look at type - - if(have_to_replace(dest.type())) - if(!replace_symbolt::replace(dest.type())) - result=false; - - // now do expression itself - - if(!have_to_replace(dest)) - return result; - - if(dest.id()==ID_symbol) - { - expr_mapt::const_iterator it= - expr_map.find(dest.get(ID_identifier)); - - if(it!=expr_map.end()) - { - dest=it->second; - return false; - } - } - - Forall_operands(it, dest) - if(!replace(*it)) - result=false; - - const irept &c_sizeof_type=dest.find(ID_C_c_sizeof_type); - - if(c_sizeof_type.is_not_nil() && - !replace_symbolt::replace( - static_cast(dest.add(ID_C_c_sizeof_type)))) - result=false; - - const irept &va_arg_type=dest.find(ID_C_va_arg_type); - - if(va_arg_type.is_not_nil() && - !replace_symbolt::replace( - static_cast(dest.add(ID_C_va_arg_type)))) - result=false; - - return result; -} diff --git a/src/analyses/replace_symbol_ext.h b/src/analyses/replace_symbol_ext.h deleted file mode 100644 index 05d7226be40..00000000000 --- a/src/analyses/replace_symbol_ext.h +++ /dev/null @@ -1,23 +0,0 @@ -/*******************************************************************\ - -Module: Modified expression replacement for constant propagator - -Author: Peter Schrammel - -\*******************************************************************/ - -/// \file -/// Modified expression replacement for constant propagator - -#ifndef CPROVER_ANALYSES_REPLACE_SYMBOL_EXT_H -#define CPROVER_ANALYSES_REPLACE_SYMBOL_EXT_H - -#include - -class replace_symbol_extt:public replace_symbolt -{ -public: - virtual bool replace(exprt &dest) const; -}; - -#endif // CPROVER_ANALYSES_REPLACE_SYMBOL_EXT_H diff --git a/src/util/replace_symbol.cpp b/src/util/replace_symbol.cpp index 51d4a140493..06ffdd7ef7e 100644 --- a/src/util/replace_symbol.cpp +++ b/src/util/replace_symbol.cpp @@ -27,9 +27,11 @@ void replace_symbolt::insert( old_expr.get_identifier(), new_expr)); } -bool replace_symbolt::replace(exprt &dest) const +bool replace_symbolt::replace( + exprt &dest, + const bool replace_with_const) const { - bool result=true; + bool result=true; // unchanged // first look at type @@ -42,33 +44,75 @@ bool replace_symbolt::replace(exprt &dest) const if(!have_to_replace(dest)) return result; - if(dest.id()==ID_symbol) + if(dest.id()==ID_member) + { + member_exprt &me=to_member_expr(dest); + + if(!replace(me.struct_op(), replace_with_const)) // Could give non l-value. + result=false; + } + else if(dest.id()==ID_index) + { + index_exprt &ie=to_index_expr(dest); + + if(!replace(ie.array(), replace_with_const)) // Could give non l-value. + result=false; + + if(!replace(ie.index())) + result=false; + } + else if(dest.id()==ID_address_of) + { + address_of_exprt &aoe=to_address_of_expr(dest); + + if(!replace(aoe.object(), false)) + result=false; + } + else if(dest.id()==ID_symbol) { + const symbol_exprt &s=to_symbol_expr(dest); + expr_mapt::const_iterator it= - expr_map.find(dest.get(ID_identifier)); + expr_map.find(s.get_identifier()); if(it!=expr_map.end()) { - dest=it->second; + const exprt &e=it->second; + + if(!replace_with_const && e.is_constant()) // Would give non l-value. + return true; + + dest=e; + return false; } } - - Forall_operands(it, dest) - if(!replace(*it)) - result=false; + else + { + Forall_operands(it, dest) + if(!replace(*it)) + result=false; + } const irept &c_sizeof_type=dest.find(ID_C_c_sizeof_type); - if(c_sizeof_type.is_not_nil() && - !replace(static_cast(dest.add(ID_C_c_sizeof_type)))) - result=false; + if(c_sizeof_type.is_not_nil()) + { + typet &type=static_cast(dest.add(ID_C_c_sizeof_type)); + + if(!replace(type)) + result=false; + } const irept &va_arg_type=dest.find(ID_C_va_arg_type); - if(va_arg_type.is_not_nil() && - !replace(static_cast(dest.add(ID_C_va_arg_type)))) - result=false; + if(va_arg_type.is_not_nil()) + { + typet &type=static_cast(dest.add(ID_C_va_arg_type)); + + if(!replace(type)) + result=false; + } return result; } diff --git a/src/util/replace_symbol.h b/src/util/replace_symbol.h index ebc1102e921..ea9b4c14701 100644 --- a/src/util/replace_symbol.h +++ b/src/util/replace_symbol.h @@ -38,7 +38,21 @@ class replace_symbolt type_map.insert(std::pair(identifier, type)); } - virtual bool replace(exprt &dest) const; + /* If you are replacing symbols with constants in an l-value, you can + * create something that is not an l-value. For example if your + * l-value is "a[i]" then substituting i for a constant results in an + * l-value but substituting a for a constant (array) wouldn't. This + * only applies to the "top level" of the expression, for example, it + * is OK to replace b with a constant array in a[b[0]]. + * + * If replace_with_const == false then it disables the rewrites that + * could result in something that is not an l-value. + */ + + virtual bool replace( + exprt &dest, + const bool replace_with_const=true) const; + virtual bool replace(typet &dest) const; void operator()(exprt &dest) const From e2fdcbf42c887d55becab39fa3501108d5b4e594 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Wed, 15 Feb 2017 17:16:02 +0000 Subject: [PATCH 004/129] constant propagator fix --- src/analyses/constant_propagator.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/analyses/constant_propagator.cpp b/src/analyses/constant_propagator.cpp index 3e6f9d41b17..e1e22baaee8 100644 --- a/src/analyses/constant_propagator.cpp +++ b/src/analyses/constant_propagator.cpp @@ -58,11 +58,17 @@ void constant_propagator_domaint::transform( output(std::cout, ai, ns); #endif + // When the domain is used with constant_propagator_ait, + // information about dirty variables and config flags are + // available. Otherwise, the below will be null and we use default + // values const constant_propagator_ait *cp= dynamic_cast(&ai); bool have_dirty=(cp!=nullptr); - assert(!values.is_bottom); + // assert(!values.is_bottom); + if(values.is_bottom) + return; if(from->is_decl()) { From 3178f1bbc79015480aedfc4285c7c8cf7de073c7 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 23 May 2017 20:46:55 +0100 Subject: [PATCH 005/129] Add is_bottom() and is_top() to ai_domain_baset and derived domains. --- src/analyses/ai.h | 4 +++ src/analyses/constant_propagator.h | 44 ++++++++++++++++-------- src/analyses/custom_bitvector_analysis.h | 22 +++++++++--- src/analyses/dependence_graph.h | 28 ++++++++++++--- src/analyses/escape_analysis.h | 22 +++++++++--- src/analyses/global_may_alias.h | 22 +++++++++--- src/analyses/interval_domain.h | 27 +++++++++------ src/analyses/invariant_set_domain.h | 20 ++++++++--- src/analyses/is_threaded.cpp | 20 ++++++++--- src/analyses/reaching_definitions.h | 26 ++++++++++---- src/analyses/uninitialized_domain.h | 20 ++++++++--- 11 files changed, 192 insertions(+), 63 deletions(-) diff --git a/src/analyses/ai.h b/src/analyses/ai.h index 3c078d2a9bb..eca4feb1d80 100644 --- a/src/analyses/ai.h +++ b/src/analyses/ai.h @@ -78,6 +78,10 @@ class ai_domain_baset // a reasonable entry-point state virtual void make_entry()=0; + virtual bool is_bottom() const=0; + + virtual bool is_top() const=0; + // also add // // bool merge(const T &b, locationt from, locationt to); diff --git a/src/analyses/constant_propagator.h b/src/analyses/constant_propagator.h index 437c7744ff8..1b98e6272fe 100644 --- a/src/analyses/constant_propagator.h +++ b/src/analyses/constant_propagator.h @@ -25,12 +25,12 @@ class constant_propagator_domaint:public ai_domain_baset locationt from, locationt to, ai_baset &ai_base, - const namespacet &ns); + const namespacet &ns) final override; virtual void output( std::ostream &out, const ai_baset &ai_base, - const namespacet &ns) const; + const namespacet &ns) const override; bool merge( const constant_propagator_domaint &other, @@ -39,23 +39,33 @@ class constant_propagator_domaint:public ai_domain_baset virtual bool ai_simplify( exprt &condition, - const namespacet &ns) const override; + const namespacet &ns) const final override; - virtual void make_bottom() + virtual void make_bottom() final override { values.set_to_bottom(); } - virtual void make_top() + virtual void make_top() final override { values.set_to_top(); } - virtual void make_entry() + virtual void make_entry() final override { make_top(); } + virtual bool is_bottom() const final override + { + return values.is_bot(); + } + + virtual bool is_top() const final override + { + return values.is_top(); + } + struct valuest { public: @@ -70,27 +80,37 @@ class constant_propagator_domaint:public ai_domain_baset // set whole state - inline void set_to_bottom() + void set_to_bottom() { replace_const.clear(); is_bottom=true; } - inline void set_to_top() + void set_to_top() { replace_const.clear(); is_bottom=false; } + bool is_bot() const + { + return is_bottom && replace_const.empty(); + } + + bool is_top() const + { + return !is_bottom && replace_const.empty(); + } + // set single identifier - inline void set_to(const irep_idt &lhs, const exprt &rhs) + void set_to(const irep_idt &lhs, const exprt &rhs) { replace_const.expr_map[lhs]=rhs; is_bottom=false; } - inline void set_to(const symbol_exprt &lhs, const exprt &rhs) + void set_to(const symbol_exprt &lhs, const exprt &rhs) { set_to(lhs.get_identifier(), rhs); } @@ -142,8 +162,6 @@ class constant_propagator_ait:public ait goto_functionst &goto_functions, const namespacet &ns):dirty(goto_functions) { - assert(false); - operator()(goto_functions, ns); replace(goto_functions, ns); } @@ -152,8 +170,6 @@ class constant_propagator_ait:public ait goto_functionst::goto_functiont &goto_function, const namespacet &ns):dirty(goto_function) { - assert(false); - operator()(goto_function, ns); replace(goto_function, ns); } diff --git a/src/analyses/custom_bitvector_analysis.h b/src/analyses/custom_bitvector_analysis.h index ff2884cc2ec..294dfb98989 100644 --- a/src/analyses/custom_bitvector_analysis.h +++ b/src/analyses/custom_bitvector_analysis.h @@ -27,32 +27,44 @@ class custom_bitvector_domaint:public ai_domain_baset locationt from, locationt to, ai_baset &ai, - const namespacet &ns) final; + const namespacet &ns) final override; void output( std::ostream &out, const ai_baset &ai, - const namespacet &ns) const final; + const namespacet &ns) const final override; - void make_bottom() final + void make_bottom() final override { may_bits.clear(); must_bits.clear(); has_values=tvt(false); } - void make_top() final + void make_top() final override { may_bits.clear(); must_bits.clear(); has_values=tvt(true); } - void make_entry() final + void make_entry() final override { make_top(); } + bool is_bottom() const final override + { + assert(!has_values.is_false() || (may_bits.empty() && must_bits.empty())); + return has_values.is_false(); + } + + bool is_top() const final override + { + assert(!has_values.is_true() || (may_bits.empty() && must_bits.empty())); + return has_values.is_true(); + } + bool merge( const custom_bitvector_domaint &b, locationt from, diff --git a/src/analyses/dependence_graph.h b/src/analyses/dependence_graph.h index 4cd7be4c589..c130aa7737c 100644 --- a/src/analyses/dependence_graph.h +++ b/src/analyses/dependence_graph.h @@ -83,12 +83,12 @@ class dep_graph_domaint:public ai_domain_baset goto_programt::const_targett from, goto_programt::const_targett to, ai_baset &ai, - const namespacet &ns) final; + const namespacet &ns) final override; void output( std::ostream &out, const ai_baset &ai, - const namespacet &ns) const final; + const namespacet &ns) const final override; jsont output_json( const ai_baset &ai, @@ -103,7 +103,7 @@ class dep_graph_domaint:public ai_domain_baset data_deps.clear(); } - void make_bottom() final + void make_bottom() final override { assert(node_id!=std::numeric_limits::max()); @@ -112,11 +112,31 @@ class dep_graph_domaint:public ai_domain_baset data_deps.clear(); } - void make_entry() final + void make_entry() final override { make_top(); } + bool is_top() const final override + { + assert(node_id!=std::numeric_limits::max()); + + assert(!has_values.is_true() || + (control_deps.empty() && data_deps.empty())); + + return has_values.is_true(); + } + + bool is_bottom() const final override + { + assert(node_id!=std::numeric_limits::max()); + + assert(!has_values.is_false() || + (control_deps.empty() && data_deps.empty())); + + return has_values.is_false(); + } + void set_node_id(node_indext id) { node_id=id; diff --git a/src/analyses/escape_analysis.h b/src/analyses/escape_analysis.h index 00f865b45e4..54c2ba408ba 100644 --- a/src/analyses/escape_analysis.h +++ b/src/analyses/escape_analysis.h @@ -32,33 +32,45 @@ class escape_domaint:public ai_domain_baset locationt from, locationt to, ai_baset &ai, - const namespacet &ns) final; + const namespacet &ns) final override; void output( std::ostream &out, const ai_baset &ai, - const namespacet &ns) const final; + const namespacet &ns) const final override; bool merge( const escape_domaint &b, locationt from, locationt to); - void make_bottom() final + void make_bottom() final override { cleanup_map.clear(); aliases.clear(); has_values=tvt(false); } - void make_top() final + void make_top() final override { cleanup_map.clear(); aliases.clear(); has_values=tvt(true); } - void make_entry() final + bool is_bottom() const override final + { + assert(!has_values.is_false() || (cleanup_map.empty() && aliases.empty())); + return has_values.is_false(); + } + + bool is_top() const override final + { + assert(!has_values.is_true() || (cleanup_map.empty() && aliases.empty())); + return has_values.is_true(); + } + + void make_entry() override final { make_top(); } diff --git a/src/analyses/global_may_alias.h b/src/analyses/global_may_alias.h index d946b371c05..f16ced0c4bd 100644 --- a/src/analyses/global_may_alias.h +++ b/src/analyses/global_may_alias.h @@ -32,35 +32,47 @@ class global_may_alias_domaint:public ai_domain_baset locationt from, locationt to, ai_baset &ai, - const namespacet &ns) final; + const namespacet &ns) final override; void output( std::ostream &out, const ai_baset &ai, - const namespacet &ns) const final; + const namespacet &ns) const final override; bool merge( const global_may_alias_domaint &b, locationt from, locationt to); - void make_bottom() final + void make_bottom() final override { aliases.clear(); has_values=tvt(false); } - void make_top() final + void make_top() final override { aliases.clear(); has_values=tvt(true); } - void make_entry() final + void make_entry() final override { make_top(); } + bool is_bottom() const final override + { + assert(!has_values.is_false() || aliases.empty()); + return has_values.is_false(); + } + + bool is_top() const final override + { + assert(!has_values.is_true() || aliases.empty()); + return has_values.is_true(); + } + typedef union_find aliasest; aliasest aliases; diff --git a/src/analyses/interval_domain.h b/src/analyses/interval_domain.h index 3076442a3ee..d4496fec4bb 100644 --- a/src/analyses/interval_domain.h +++ b/src/analyses/interval_domain.h @@ -36,12 +36,12 @@ class interval_domaint:public ai_domain_baset locationt from, locationt to, ai_baset &ai, - const namespacet &ns) final; + const namespacet &ns) final override; void output( std::ostream &out, const ai_baset &ai, - const namespacet &ns) const final; + const namespacet &ns) const override; protected: bool join(const interval_domaint &b); @@ -56,7 +56,7 @@ class interval_domaint:public ai_domain_baset } // no states - void make_bottom() final + void make_bottom() final override { int_map.clear(); float_map.clear(); @@ -64,18 +64,30 @@ class interval_domaint:public ai_domain_baset } // all states - void make_top() final + void make_top() final override { int_map.clear(); float_map.clear(); bottom=false; } - void make_entry() final + void make_entry() final override { make_top(); } + bool is_bottom() const override final + { + // assert(!bottom || (int_map.empty() && float_map.empty())); + + return bottom; + } + + bool is_top() const override final + { + return !bottom && int_map.empty() && float_map.empty(); + } + exprt make_expression(const symbol_exprt &) const; void assume(const exprt &, const namespacet &); @@ -90,11 +102,6 @@ class interval_domaint:public ai_domain_baset return src.id()==ID_floatbv; } - bool is_bottom() const - { - return bottom; - } - virtual bool ai_simplify( exprt &condition, const namespacet &ns) const override; diff --git a/src/analyses/invariant_set_domain.h b/src/analyses/invariant_set_domain.h index 4d38b6b2657..367e987c709 100644 --- a/src/analyses/invariant_set_domain.h +++ b/src/analyses/invariant_set_domain.h @@ -44,7 +44,7 @@ class invariant_set_domaint:public ai_domain_baset void output( std::ostream &out, const ai_baset &ai, - const namespacet &ns) const final + const namespacet &ns) const final override { if(has_values.is_known()) out << has_values.to_string() << '\n'; @@ -56,25 +56,35 @@ class invariant_set_domaint:public ai_domain_baset locationt from_l, locationt to_l, ai_baset &ai, - const namespacet &ns) final; + const namespacet &ns) final override; - void make_top() final + void make_top() final override { invariant_set.make_true(); has_values=tvt(true); } - void make_bottom() final + void make_bottom() final override { invariant_set.make_false(); has_values=tvt(false); } - void make_entry() final + void make_entry() final override { invariant_set.make_true(); has_values=tvt(true); } + + bool is_top() const override final + { + return has_values.is_true(); + } + + bool is_bottom() const override final + { + return has_values.is_false(); + } }; #endif // CPROVER_ANALYSES_INVARIANT_SET_DOMAIN_H diff --git a/src/analyses/is_threaded.cpp b/src/analyses/is_threaded.cpp index 64b1e48f959..d6276cbdb27 100644 --- a/src/analyses/is_threaded.cpp +++ b/src/analyses/is_threaded.cpp @@ -51,7 +51,7 @@ class is_threaded_domaint:public ai_domain_baset locationt from, locationt to, ai_baset &ai, - const namespacet &ns) final + const namespacet &ns) final override { // assert(reachable); @@ -62,23 +62,35 @@ class is_threaded_domaint:public ai_domain_baset is_threaded=true; } - void make_bottom() final + void make_bottom() final override { reachable=false; is_threaded=false; } - void make_top() final + void make_top() final override { reachable=true; is_threaded=true; } - void make_entry() final + void make_entry() final override { reachable=true; is_threaded=false; } + + bool is_bottom() const override final + { + assert(reachable || !is_threaded); + + return !reachable; + } + + bool is_top() const override final + { + return reachable && is_threaded; + } }; void is_threadedt::compute(const goto_functionst &goto_functions) diff --git a/src/analyses/reaching_definitions.h b/src/analyses/reaching_definitions.h index 2cc7d815fa3..a9a52a062b5 100644 --- a/src/analyses/reaching_definitions.h +++ b/src/analyses/reaching_definitions.h @@ -116,17 +116,17 @@ class rd_range_domaint:public ai_domain_baset locationt from, locationt to, ai_baset &ai, - const namespacet &ns) final; + const namespacet &ns) final override; void output( std::ostream &out, const ai_baset &ai, - const namespacet &ns) const final + const namespacet &ns) const final override { output(out); } - void make_top() final + void make_top() final override { values.clear(); if(bv_container) @@ -134,7 +134,7 @@ class rd_range_domaint:public ai_domain_baset has_values=tvt(true); } - void make_bottom() final + void make_bottom() final override { values.clear(); if(bv_container) @@ -142,11 +142,23 @@ class rd_range_domaint:public ai_domain_baset has_values=tvt(false); } - void make_entry() final + void make_entry() final override { make_top(); } + bool is_top() const override final + { + assert(!has_values.is_true() || values.empty()); + return has_values.is_true(); + } + + bool is_bottom() const override final + { + assert(!has_values.is_false() || values.empty()); + return has_values.is_false(); + } + // returns true iff there is s.th. new bool merge( const rd_range_domaint &other, @@ -252,9 +264,9 @@ class reaching_definitions_analysist: virtual ~reaching_definitions_analysist(); virtual void initialize( - const goto_functionst &goto_functions); + const goto_functionst &goto_functions) override; - virtual statet &get_state(goto_programt::const_targett l) + virtual statet &get_state(goto_programt::const_targett l) override { statet &s=concurrency_aware_ait::get_state(l); diff --git a/src/analyses/uninitialized_domain.h b/src/analyses/uninitialized_domain.h index a48f9954388..c95222e5027 100644 --- a/src/analyses/uninitialized_domain.h +++ b/src/analyses/uninitialized_domain.h @@ -33,30 +33,42 @@ class uninitialized_domaint:public ai_domain_baset locationt from, locationt to, ai_baset &ai, - const namespacet &ns) final; + const namespacet &ns) final override; void output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const final; - void make_top() final + void make_top() final override { uninitialized.clear(); has_values=tvt(true); } - void make_bottom() final + void make_bottom() final override { uninitialized.clear(); has_values=tvt(false); } - void make_entry() final + void make_entry() final override { make_top(); } + bool is_top() const override final + { + assert(!has_values.is_true() || uninitialized.empty()); + return has_values.is_true(); + } + + bool is_bottom() const override final + { + assert(!has_values.is_false() || uninitialized.empty()); + return has_values.is_false(); + } + // returns true iff there is s.th. new bool merge( const uninitialized_domaint &other, From 5606ce5bfa9dfe6cec4683f15efce63b534a4899 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 23 May 2017 20:41:23 +0100 Subject: [PATCH 006/129] Use is_bottom() to catch unreachable functions. --- src/analyses/ai.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/analyses/ai.cpp b/src/analyses/ai.cpp index 1eca272c19d..dfde5bd401f 100644 --- a/src/analyses/ai.cpp +++ b/src/analyses/ai.cpp @@ -37,7 +37,7 @@ xmlt ai_domain_baset::output_xml( { std::ostringstream out; output(out, ai, ns); - xmlt xml("domain"); + xmlt xml("abstract_state"); xml.data=out.str(); return xml; } @@ -166,7 +166,7 @@ jsont ai_baset::output_json( json_numbert(std::to_string(i_it->location_number)); location["sourceLocation"]= json_stringt(i_it->source_location.as_string()); - location["domain"]=find_state(i_it).output_json(*this, ns); + location["abstractState"]=find_state(i_it).output_json(*this, ns); // Ideally we need output_instruction_json std::ostringstream out; @@ -427,7 +427,12 @@ bool ai_baset::do_function_call( assert(l_end->is_end_function()); // do edge from end of function to instruction after call - std::unique_ptr tmp_state(make_temporary_state(get_state(l_end))); + const statet &end_state=get_state(l_end); + + if(end_state.is_bottom()) + return false; // function exit point not reachable + + std::unique_ptr tmp_state(make_temporary_state(end_state)); tmp_state->transform(l_end, l_return, *this, ns); // Propagate those From 7cee75ed665f15c30392ecc9e71b0aa25e81b212 Mon Sep 17 00:00:00 2001 From: martin Date: Fri, 16 Dec 2016 16:42:27 +0000 Subject: [PATCH 007/129] Refactor goto-analyzer so that task, analysis, domain and output can be picked independently. --- src/goto-analyzer/Makefile | 2 + .../goto_analyzer_parse_options.cpp | 183 +++++++++-- .../goto_analyzer_parse_options.h | 7 +- src/goto-analyzer/static_analyzer.cpp | 162 +++++----- src/goto-analyzer/static_analyzer.h | 3 +- src/goto-analyzer/static_show_domain.cpp | 87 ++++++ src/goto-analyzer/static_show_domain.h | 26 ++ src/goto-analyzer/static_simplifier.cpp | 284 ++++++++++++++++++ src/goto-analyzer/static_simplifier.h | 26 ++ 9 files changed, 687 insertions(+), 93 deletions(-) create mode 100644 src/goto-analyzer/static_show_domain.cpp create mode 100644 src/goto-analyzer/static_show_domain.h create mode 100644 src/goto-analyzer/static_simplifier.cpp create mode 100644 src/goto-analyzer/static_simplifier.h diff --git a/src/goto-analyzer/Makefile b/src/goto-analyzer/Makefile index da9e1c50d7d..f7eac67e6fb 100644 --- a/src/goto-analyzer/Makefile +++ b/src/goto-analyzer/Makefile @@ -4,6 +4,8 @@ SRC = goto_analyzer_main.cpp \ taint_analysis.cpp \ taint_parser.cpp \ unreachable_instructions.cpp \ + static_simplifier.cpp \ + static_show_domain.cpp \ # Empty last line OBJ += ../ansi-c/ansi-c$(LIBEXT) \ diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index 904ab58768e..cc0748bcb17 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -36,6 +36,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include +#include #include #include @@ -52,6 +54,8 @@ Author: Daniel Kroening, kroening@kroening.com #include "taint_analysis.h" #include "unreachable_instructions.h" #include "static_analyzer.h" +#include "static_show_domain.h" +#include "static_simplifier.h" goto_analyzer_parse_optionst::goto_analyzer_parse_optionst( int argc, @@ -130,6 +134,100 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) if(cmdline.isset("error-label")) options.set_option("error-label", cmdline.get_values("error-label")); #endif + + + // Output format choice + options.set_option("text", false); + options.set_option("json", false); + options.set_option("xml", false); + options.set_option("outfile", "-"); + + if(cmdline.isset("text")) + { + options.set_option("text", true); + options.set_option("outfile", cmdline.get_value("text")); + } + else if(cmdline.isset("json")) + { + options.set_option("json", true); + options.set_option("outfile", cmdline.get_value("json")); + } + else if(cmdline.isset("xml")) + { + options.set_option("xml", true); + options.set_option("outfile", cmdline.get_value("xml")); + } + else + { + options.set_option("text", true); + } + + + // Task options + options.set_option( "show", false); + options.set_option( "verify", false); + options.set_option("simplify", false); + + if(cmdline.isset("show") || + cmdline.isset("show-intervals") || + cmdline.isset("show-non-null")) + options.set_option("show", true); + else if(cmdline.isset("verify")) + options.set_option("verify", true); + else if(cmdline.isset("simplify")) + { + options.set_option("simplify", true); + options.set_option("outfile", cmdline.get_value("simplify")); + } + + if(!(options.get_bool_option("show") || + options.get_bool_option("verify") || + options.get_bool_option("simplify"))) + { + status() << "Task defaults to --show" << eom; + options.set_option("show", true); + } + + + // Abstract interpreter choice + options.set_option("flow-sensitive", false); + options.set_option("concurrent", false); + + if(cmdline.isset("flow-sensitive")) + options.set_option("flow-sensitive", true); + else if(cmdline.isset("concurrent")) + options.set_option("concurrent", true); + else + { + is_threadedt is_threaded(goto_model.goto_functions); + bool contains_concurrent_code=is_threaded(); + + options.set_option("flow-sensitive", !contains_concurrent_code); + options.set_option("concurrent", contains_concurrent_code); + } + + + // Domain choice + options.set_option("constants", false); + options.set_option("intervals", false); + options.set_option("non-null", false); + + if(cmdline.isset("intervals") || + cmdline.isset("show-intervals")) + options.set_option("intervals", true); + else if(cmdline.isset("non-null") || + cmdline.isset("show-non-null")) + options.set_option("non-null", true); + else if(cmdline.isset("constants")) + options.set_option("constants", true); + + if(!(options.get_bool_option("constants") || + options.get_bool_option("intervals") || + options.get_bool_option("non-null"))) + { + status() << "Domain defaults to --constants" << eom; + options.set_option("constants", true); + } } /// invoke main modules @@ -177,9 +275,12 @@ int goto_analyzer_parse_optionst::doit() else { std::string json_file=cmdline.get_value("json"); - bool result= - taint_analysis( - goto_model, taint_file, get_message_handler(), false, json_file); + bool result=taint_analysis( + goto_model, + taint_file, + get_message_handler(), + false, + json_file); return result?10:0; } } @@ -290,17 +391,47 @@ int goto_analyzer_parse_optionst::doit() return 0; } - if(cmdline.isset("non-null") || - cmdline.isset("intervals")) + + // Output file factory + std::ostream *out; + const std::string outfile=options.get_option("outfile"); + if(outfile=="-") + out=&std::cout; + else { - optionst options; - options.set_option("json", cmdline.get_value("json")); - options.set_option("xml", cmdline.get_value("xml")); - bool result= - static_analyzer(goto_model, options, get_message_handler()); - return result?10:0; + out=new std::ofstream(outfile); + if(!*out) + { + error() << "Failed to open output file `" + << outfile << "'" << eom; + return 6; + } + } + + + // Run the analysis + bool result=true; + if(options.get_bool_option("show")) + result=static_show_domain(goto_model, options, get_message_handler(), *out); + + else if(options.get_bool_option("verify")) + result= static_analyzer(goto_model, options, get_message_handler(), *out); + + else if(options.get_bool_option("simplify")) + result= static_simplifier(goto_model, options, get_message_handler(), *out); + else + { + error() << "No task given" << eom; + return 6; } + if(out!=&std::cout) + delete out; + + return result?10:0; + + + // Final defensive error case error() << "no analysis option given -- consider reading --help" << eom; return 6; @@ -441,8 +572,29 @@ void goto_analyzer_parse_optionst::help() " goto-analyzer [-h] [--help] show help\n" " goto-analyzer file.c ... source file names\n" "\n" - "Analyses:\n" + "Task options:\n" + " --show display the abstract domains\n" + // NOLINTNEXTLINE(whitespace/line_length) + " --verify use the abstract domains to check assertions\n" + // NOLINTNEXTLINE(whitespace/line_length) + " --simplify file_name use the abstract domains to simplify the program\n" + "\n" + "Abstract interpreter options:\n" + " --flow-sensitive use flow-sensitive abstract interpreter\n" + " --concurrent use concurrent abstract interpreter\n" "\n" + "Domain options:\n" + " --constants constant abstraction\n" + " --intervals interval abstraction\n" + " --non-null non-null abstraction\n" + "\n" + "Output options:\n" + " --text file_name output results in plain text to given file\n" + // NOLINTNEXTLINE(whitespace/line_length) + " --json file_name output results in JSON format to given file\n" + " --xml file_name output results in XML format to given file\n" + "\n" + "Other analyses:\n" // NOLINTNEXTLINE(whitespace/line_length) " --taint file_name perform taint analysis using rules in given file\n" " --unreachable-instructions list dead code\n" @@ -450,13 +602,6 @@ void goto_analyzer_parse_optionst::help() " --unreachable-functions list functions unreachable from the entry point\n" // NOLINTNEXTLINE(whitespace/line_length) " --reachable-functions list functions reachable from the entry point\n" - " --intervals interval analysis\n" - " --non-null non-null analysis\n" - "\n" - "Analysis options:\n" - // NOLINTNEXTLINE(whitespace/line_length) - " --json file_name output results in JSON format to given file\n" - " --xml file_name output results in XML format to given file\n" "\n" "C/C++ frontend options:\n" " -I path set include path (C/C++)\n" diff --git a/src/goto-analyzer/goto_analyzer_parse_options.h b/src/goto-analyzer/goto_analyzer_parse_options.h index 48b299049b9..f4330a5260f 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.h +++ b/src/goto-analyzer/goto_analyzer_parse_options.h @@ -41,11 +41,14 @@ class optionst; "(gcc)(arch):" \ "(taint):(show-taint)" \ "(show-local-may-alias)" \ - "(json):(xml):" \ + "(json):(xml):(text):" \ "(unreachable-instructions)(unreachable-functions)" \ "(reachable-functions)" \ "(intervals)(show-intervals)" \ - "(non-null)(show-non-null)" + "(non-null)(show-non-null)" \ + "(constants)" \ + "(show)(verify)(simplify):" \ + "(flow-sensitive)(concurrent)" class goto_analyzer_parse_optionst: public parse_options_baset, diff --git a/src/goto-analyzer/static_analyzer.cpp b/src/goto-analyzer/static_analyzer.cpp index 4125e5d44cb..8f1f300be7e 100644 --- a/src/goto-analyzer/static_analyzer.cpp +++ b/src/goto-analyzer/static_analyzer.cpp @@ -9,25 +9,28 @@ Author: Daniel Kroening, kroening@kroening.com #include -#include #include #include #include +#include #include "static_analyzer.h" +template class static_analyzert:public messaget { public: static_analyzert( const goto_modelt &_goto_model, const optionst &_options, - message_handlert &_message_handler): + message_handlert &_message_handler, + std::ostream &_out): messaget(_message_handler), goto_functions(_goto_model.goto_functions), ns(_goto_model.symbol_table), - options(_options) + options(_options), + out(_out) { } @@ -37,43 +40,39 @@ class static_analyzert:public messaget const goto_functionst &goto_functions; const namespacet ns; const optionst &options; + std::ostream &out; // analyses - ait interval_analysis; + analyzerT domain; void plain_text_report(); - void json_report(const std::string &); - void xml_report(const std::string &); - - tvt eval(goto_programt::const_targett); + void json_report(); + void xml_report(); }; -bool static_analyzert::operator()() + +/// Run the analysis, check the assertions and report in the correct format. +/// \return false on success, true on failure. +template +bool static_analyzert::operator()() { - status() << "performing interval analysis" << eom; - interval_analysis(goto_functions, ns); + status() << "Performing analysis" << eom; + domain(goto_functions, ns); - if(!options.get_option("json").empty()) - json_report(options.get_option("json")); - else if(!options.get_option("xml").empty()) - xml_report(options.get_option("xml")); + if(options.get_bool_option("json")) + json_report(); + else if(options.get_bool_option("xml")) + xml_report(); else plain_text_report(); return false; } -tvt static_analyzert::eval(goto_programt::const_targett t) -{ - exprt guard=t->guard; - interval_domaint d=interval_analysis[t]; - d.assume(not_exprt(guard), ns); - if(d.is_bottom()) - return tvt(true); - return tvt::unknown(); -} -void static_analyzert::plain_text_report() +/// Check the assertions and give results as text via out. +template +void static_analyzert::plain_text_report() { unsigned pass=0, fail=0, unknown=0; @@ -92,7 +91,7 @@ void static_analyzert::plain_text_report() if(!i_it->is_assert()) continue; - tvt r=eval(i_it); + exprt simplified=domain[i_it].domain_simplify(i_it->guard, ns); result() << '[' << i_it->source_location.get_property_id() << ']' << ' '; @@ -101,30 +100,26 @@ void static_analyzert::plain_text_report() if(!i_it->source_location.get_comment().empty()) result() << ", " << i_it->source_location.get_comment(); result() << ": "; - if(r.is_true()) - result() << "SUCCESS"; - else if(r.is_false()) - result() << "FAILURE"; + if(simplified.is_true()) + { result() << "SUCCESS"; pass++; } + else if(simplified.is_false()) + { result() << "FAILURE (if reachable)"; fail++; } else - result() << "UNKNOWN"; + { result() << "UNKNOWN"; unknown++; } result() << eom; - if(r.is_true()) - pass++; - else if(r.is_false()) - fail++; - else - unknown++; } status() << '\n'; } - - status() << "SUMMARY: " << pass << " pass, " << fail << " fail, " + status() << "SUMMARY: " << pass << " pass, " << fail << " fail if reachable, " << unknown << " unknown\n"; } -void static_analyzert::json_report(const std::string &file_name) + +/// Check the assertions and give results as JSON via out. +template +void static_analyzert::json_report() { json_arrayt json_result; @@ -141,14 +136,14 @@ void static_analyzert::json_report(const std::string &file_name) if(!i_it->is_assert()) continue; - tvt r=eval(i_it); + exprt simplified=domain[i_it].domain_simplify(i_it->guard, ns); json_objectt &j=json_result.push_back().make_object(); - if(r.is_true()) + if(simplified.is_true()) j["status"]=json_stringt("SUCCESS"); - else if(r.is_false()) - j["status"]=json_stringt("FAILURE"); + else if(simplified.is_false()) + j["status"]=json_stringt("FAILURE (if reachable)"); else j["status"]=json_stringt("UNKNOWN"); @@ -158,20 +153,14 @@ void static_analyzert::json_report(const std::string &file_name) i_it->source_location.get_comment())); } } - - std::ofstream out(file_name); - if(!out) - { - error() << "failed to open JSON output file `" - << file_name << "'" << eom; - return; - } - - status() << "Writing report to `" << file_name << "'" << eom; + status() << "Writing JSON report" << eom; out << json_result; } -void static_analyzert::xml_report(const std::string &file_name) + +/// Check the assertions and give results as XML via out. +template +void static_analyzert::xml_report() { xmlt xml_result; @@ -188,14 +177,14 @@ void static_analyzert::xml_report(const std::string &file_name) if(!i_it->is_assert()) continue; - tvt r=eval(i_it); + exprt simplified=domain[i_it].domain_simplify(i_it->guard, ns); xmlt &x=xml_result.new_element("result"); - if(r.is_true()) + if(simplified.is_true()) x.set_attribute("status", "SUCCESS"); - else if(r.is_false()) - x.set_attribute("status", "FAILURE"); + else if(simplified.is_false()) + x.set_attribute("status", "FAILURE (if reachable)"); else x.set_attribute("status", "UNKNOWN"); @@ -206,25 +195,56 @@ void static_analyzert::xml_report(const std::string &file_name) } } - std::ofstream out(file_name); - if(!out) - { - error() << "failed to open XML output file `" - << file_name << "'" << eom; - return; - } - - status() << "Writing report to `" << file_name << "'" << eom; + status() << "Writing XML report" << eom; out << xml_result; } +/// Runs the analyzer, check assertions and generate a report via out +/// \param goto_model : the program to check +/// \param options : the options giving the domain and output +/// \param out : the output channel to use +/// \return false on success, true on failure bool static_analyzer( const goto_modelt &goto_model, const optionst &options, - message_handlert &message_handler) + message_handlert &message_handler, + std::ostream &out) { - return static_analyzert( - goto_model, options, message_handler)(); + if(options.get_bool_option("flow-sensitive")) + { + if(options.get_bool_option("constants")) + return static_analyzert > + (goto_model, options, message_handler, out)(); + + else if(options.get_bool_option("intervals")) + return static_analyzert > + (goto_model, options, message_handler, out)(); + + // else if(options.get_bool_option("non-null")) + // return static_analyzert > + // (goto_model, options, message_handler, out)(); + } + else if(options.get_bool_option("concurrent")) + { + // Constant and interval don't have merge_shared yet +#if 0 + if(options.get_bool_option("constants")) + return static_analyzert > + (goto_model, options, message_handler, out)(); + + else if(options.get_bool_option("intervals")) + return static_analyzert > + (goto_model, options, message_handler, out)(); + + // else if(options.get_bool_option("non-null")) + // return static_analyzert > + // (goto_model, options, message_handler, out)(); +#endif + } + + messaget m(message_handler); + m.status() << "Task / Interpreter / Domain combination not supported" << messaget::eom; + return true; } void show_intervals( diff --git a/src/goto-analyzer/static_analyzer.h b/src/goto-analyzer/static_analyzer.h index fdab261d8c1..223ce348a93 100644 --- a/src/goto-analyzer/static_analyzer.h +++ b/src/goto-analyzer/static_analyzer.h @@ -21,7 +21,8 @@ Author: Daniel Kroening, kroening@kroening.com bool static_analyzer( const goto_modelt &, const optionst &, - message_handlert &); + message_handlert &, + std::ostream &); void show_intervals( const goto_modelt &, diff --git a/src/goto-analyzer/static_show_domain.cpp b/src/goto-analyzer/static_show_domain.cpp new file mode 100644 index 00000000000..a3a2616c152 --- /dev/null +++ b/src/goto-analyzer/static_show_domain.cpp @@ -0,0 +1,87 @@ +/*******************************************************************\ + +Module: + +Author: Martin Brain, martin.brain@cs.ox.ac.uk + +\*******************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "static_show_domain.h" + +/*******************************************************************\ + +Function: static_show_domain + + Inputs: The goto_model to analyze, options giving the domain and output, + the message handler and output stream. + + Outputs: The abstract domain via out. + + Purpose: Runs the analyzer and then prints out the domain. + +\*******************************************************************/ + +bool static_show_domain( + const goto_modelt &goto_model, + const optionst &options, + message_handlert &message_handler, + std::ostream &out) +{ + ai_baset *domain=NULL; + + if(options.get_bool_option("flow-sensitive")) + { + if(options.get_bool_option("constants")) + domain=new ait(); + + else if(options.get_bool_option("intervals")) + domain=new ait(); + + // else if(options.get_bool_option("non-null")) + // domain=new ait(); + } + else if(options.get_bool_option("concurrent")) + { + // Constant and interval don't have merge_shared yet +#if 0 + if(options.get_bool_option("constants")) + domain=new concurrency_aware_ait(); + + else if(options.get_bool_option("intervals")) + domain=new concurrency_aware_ait(); + + // else if(options.get_bool_option("non-null")) + // domain=new concurrency_aware_ait(); +#endif + } + + if(domain==NULL) + { + messaget m(message_handler); + m.status() << "Task / Interpreter / Domain combination not supported" + << messaget::eom; + return true; + } + + // status() << "Performing analysis" << eom; + (*domain)(goto_model); + + if(options.get_bool_option("json")) + out << domain->output_json(goto_model); + else if(options.get_bool_option("xml")) + out << domain->output_xml(goto_model); + else + domain->output(goto_model, out); + + delete domain; + return false; +} diff --git a/src/goto-analyzer/static_show_domain.h b/src/goto-analyzer/static_show_domain.h new file mode 100644 index 00000000000..3f0e7da3680 --- /dev/null +++ b/src/goto-analyzer/static_show_domain.h @@ -0,0 +1,26 @@ +/*******************************************************************\ + +Module: + +Author: Martin Brain, martin.brain@cs.ox.ac.uk + +\*******************************************************************/ + +#ifndef CPROVER_GOTO_ANALYZER_STATIC_SHOW_DOMAIN_H +#define CPROVER_GOTO_ANALYZER_STATIC_SHOW_DOMAIN_H + +#include + +#include +#include +#include + +#include + +bool static_show_domain( + const goto_modelt &, + const optionst &, + message_handlert &, + std::ostream &); + +#endif diff --git a/src/goto-analyzer/static_simplifier.cpp b/src/goto-analyzer/static_simplifier.cpp new file mode 100644 index 00000000000..fe7118563e3 --- /dev/null +++ b/src/goto-analyzer/static_simplifier.cpp @@ -0,0 +1,284 @@ +/*******************************************************************\ + +Module: + +Author: Lucas Cordeiro, lucas.cordeiro@cs.ox.ac.uk + +\*******************************************************************/ + +// #define DEBUG + +#ifdef DEBUG +#include +#endif + +#include + +#include + +#include +#include + +#include "static_simplifier.h" + +template +class static_simplifiert:public messaget +{ +public: + static_simplifiert( + goto_modelt &_goto_model, + const optionst &_options, + message_handlert &_message_handler, + std::ostream &_out): + messaget(_message_handler), + goto_functions(_goto_model.goto_functions), + ns(_goto_model.symbol_table), + options(_options), + out(_out) + { + } + + bool operator()(void); + +protected: + goto_functionst &goto_functions; + const namespacet ns; + const optionst &options; + std::ostream &out; + + // analyses + analyzerT domain; + + void simplify_program(void); + unsigned simplify_guard(goto_programt::instructionst::iterator &i_it); +}; + +/*******************************************************************\ + +Function: static_simplifiert::operator() + + Inputs: None. + + Outputs: false on success, true on failure. + + Purpose: Run the analysis, check the assertions and report in the correct format. + +\*******************************************************************/ + +template +bool static_simplifiert::operator()(void) +{ + status() << "Performing analysis" << eom; + domain(goto_functions, ns); + + status() << "Simplifying program" << eom; + simplify_program(); + + status() << "Writing goto binary" << eom; + return write_goto_binary(out, ns.get_symbol_table(), goto_functions); +} + + +/*******************************************************************\ + +Function: static_simplifiert::simplify_guard + + Inputs: An iterator pointing to an instruction. + + Outputs: 1 if simplified, 0 if not. + + Purpose: Simplifies the instruction's guard using the information in the abstract domain. + +\*******************************************************************/ + +template +unsigned static_simplifiert::simplify_guard( + goto_programt::instructionst::iterator &i_it) +{ + exprt simplified=domain[i_it].domain_simplify(i_it->guard, ns); + unsigned return_value=(simplified==i_it->guard) ? 0 : 1; + i_it->guard=simplified; + return return_value; +} + +/*******************************************************************\ + +Function: static_simplifiert::simplify_program + + Inputs: None. + + Outputs: None. + + Purpose: Simplifies the program using the information in the abstract domain. + +\*******************************************************************/ + +template +void static_simplifiert::simplify_program() +{ + struct counterst + { + unsigned asserts; + unsigned assumes; + unsigned gotos; + unsigned assigns; + unsigned function_calls; + }; + + counterst simplified={0, 0, 0, 0, 0}; + counterst unmodified={0, 0, 0, 0, 0}; + + Forall_goto_functions(f_it, goto_functions) + { + Forall_goto_program_instructions(i_it, f_it->second.body) + { + if(i_it->is_assert()) + { + unsigned result=simplify_guard(i_it); + simplified.asserts+=result; + unmodified.asserts+=(1-result); + } + else if(i_it->is_assume()) + { + unsigned result=simplify_guard(i_it); + simplified.assumes+=result; + unmodified.assumes+=(1-result); + } + else if(i_it->is_goto()) + { + unsigned result=simplify_guard(i_it); + simplified.gotos+=result; + unmodified.gotos+=(1-result); + } + else if(i_it->is_assign()) + { + code_assignt assign(to_code_assign(i_it->code)); + + /* + ** Simplification needs to be aware of which side of the + ** expression it is handling as: + ** i=j + ** should simplify to i=1, not to 0=1. + */ + + exprt simp_lhs=domain[i_it].domain_simplify(assign.lhs(), ns, true); + exprt simp_rhs=domain[i_it].domain_simplify(assign.rhs(), ns, false); + + unsigned result=(simp_lhs==assign.lhs() && + simp_rhs==assign.rhs()) ? 0 : 1; + simplified.assigns+=result; + unmodified.assigns+=(1-result); + + assign.lhs()=simp_lhs; + assign.rhs()=simp_rhs; + i_it->code=assign; + } + else if(i_it->is_function_call()) + { + unsigned result=0; + code_function_callt fcall(to_code_function_call(i_it->code)); + + exprt new_function=domain[i_it].domain_simplify(fcall.function(), ns); + result|=(new_function==fcall.function()) ? 0 : 1; + fcall.function()=new_function; + + exprt::operandst &args=fcall.arguments(); + + for(exprt::operandst::iterator o_it=args.begin(); + o_it!=args.end(); + ++o_it) + { + exprt new_arg=domain[i_it].domain_simplify(*o_it, ns); + result|=(new_arg==*o_it) ? 0 : 1; + *o_it=new_arg; + } + + i_it->code=fcall; + + simplified.function_calls+=result; + unmodified.function_calls+=(1-result); + } + } + } + + // Make sure the references are correct. + goto_functions.update(); + + + status() << "SIMPLIFIED: " + << " assert: " << simplified.asserts + << ", assume: " << simplified.assumes + << ", goto: " << simplified.gotos + << ", assigns: " << simplified.assigns + << ", function calls: " << simplified.function_calls + << "\n" + << "UNMODIFIED: " + << " assert: " << unmodified.asserts + << ", assume: " << unmodified.assumes + << ", goto: " << unmodified.gotos + << ", assigns: " << unmodified.assigns + << ", function calls: " << unmodified.function_calls + << eom; + + return; +} + + + + +/*******************************************************************\ + +Function: static_simplifier + + Inputs: The goto_model to analyze and simplify, options giving the domain, + the message handler and output stream. + + Outputs: The simplified goto binary via out. + + Purpose: Runs the analyzer, simplifies and then outputs. + +\*******************************************************************/ + +bool static_simplifier( + goto_modelt &goto_model, + const optionst &options, + message_handlert &message_handler, + std::ostream &out) +{ + if(options.get_bool_option("flow-sensitive")) + { + if(options.get_bool_option("constants")) + return static_simplifiert > + (goto_model, options, message_handler, out)(); + + else if(options.get_bool_option("intervals")) + return static_simplifiert > + (goto_model, options, message_handler, out)(); + + // else if(options.get_bool_option("non-null")) + // return static_simplifiert > + // (goto_model, options, message_handler, out)(); + } + else if(options.get_bool_option("concurrent")) + { + // Constant and interval don't have merge_shared yet +#if 0 + if(options.get_bool_option("constants")) + return static_simplifiert > + (goto_model, options, message_handler, out)(); + + else if(options.get_bool_option("intervals")) + return static_simplifiert > + (goto_model, options, message_handler, out)(); + + // else if(options.get_bool_option("non-null")) + // return static_simplifiert > + // (goto_model, options, message_handler, out)(); +#endif + } + + messaget m(message_handler); + m.status() << "Task / Interpreter / Domain combination not supported" + << messaget::eom; + return true; +} diff --git a/src/goto-analyzer/static_simplifier.h b/src/goto-analyzer/static_simplifier.h new file mode 100644 index 00000000000..c9d4e156b7a --- /dev/null +++ b/src/goto-analyzer/static_simplifier.h @@ -0,0 +1,26 @@ +/*******************************************************************\ + +Module: + +Author: Lucas Cordeiro, lucas.cordeiro@cs.ox.ac.uk + +\*******************************************************************/ + +#ifndef CPROVER_GOTO_ANALYZER_STATIC_SIMPLIFIER_H +#define CPROVER_GOTO_ANALYZER_STATIC_SIMPLIFIER_H + +#include + +#include +#include +#include + +#include + +bool static_simplifier( + goto_modelt &, + const optionst &, + message_handlert &, + std::ostream &); + +#endif From 5f6ecbea06c9d52d45101e4cdf835361102ccad5 Mon Sep 17 00:00:00 2001 From: Martin Brain Date: Fri, 9 Sep 2016 08:07:36 +0100 Subject: [PATCH 008/129] Remove the special case handling of --show-intervals. The option string --show --intervals is more flexible, --show-intervals is now an alias. --- src/goto-analyzer/goto_analyzer_parse_options.cpp | 6 ------ src/goto-analyzer/static_analyzer.cpp | 9 --------- src/goto-analyzer/static_analyzer.h | 4 ---- 3 files changed, 19 deletions(-) diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index cc0748bcb17..fe74c05cd7b 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -385,12 +385,6 @@ int goto_analyzer_parse_optionst::doit() if(set_properties()) return 7; - if(cmdline.isset("show-intervals")) - { - show_intervals(goto_model, std::cout); - return 0; - } - // Output file factory std::ostream *out; diff --git a/src/goto-analyzer/static_analyzer.cpp b/src/goto-analyzer/static_analyzer.cpp index 8f1f300be7e..a9b227c62e8 100644 --- a/src/goto-analyzer/static_analyzer.cpp +++ b/src/goto-analyzer/static_analyzer.cpp @@ -246,12 +246,3 @@ bool static_analyzer( m.status() << "Task / Interpreter / Domain combination not supported" << messaget::eom; return true; } - -void show_intervals( - const goto_modelt &goto_model, - std::ostream &out) -{ - ait interval_analysis; - interval_analysis(goto_model); - interval_analysis.output(goto_model, out); -} diff --git a/src/goto-analyzer/static_analyzer.h b/src/goto-analyzer/static_analyzer.h index 223ce348a93..649a5f693f7 100644 --- a/src/goto-analyzer/static_analyzer.h +++ b/src/goto-analyzer/static_analyzer.h @@ -24,8 +24,4 @@ bool static_analyzer( message_handlert &, std::ostream &); -void show_intervals( - const goto_modelt &, - std::ostream &); - #endif // CPROVER_GOTO_ANALYZER_STATIC_ANALYZER_H From 93b8f8c3f74ae2cd387e07cf8f01bf00a72d3271 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 22 May 2017 20:19:17 +0100 Subject: [PATCH 009/129] Add support for dependency graph display. --- .../goto_analyzer_parse_options.cpp | 20 ++++++++++--- .../goto_analyzer_parse_options.h | 3 +- src/goto-analyzer/static_show_domain.cpp | 28 +++++++++++++++---- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index fe74c05cd7b..9c687aabe20 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -140,6 +140,7 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) options.set_option("text", false); options.set_option("json", false); options.set_option("xml", false); + options.set_option("dot", false); options.set_option("outfile", "-"); if(cmdline.isset("text")) @@ -157,6 +158,11 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) options.set_option("xml", true); options.set_option("outfile", cmdline.get_value("xml")); } + else if (cmdline.isset("dot")) + { + options.set_option("dot", true); + options.set_option("outfile", cmdline.get_value("dot")); + } else { options.set_option("text", true); @@ -211,6 +217,7 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) options.set_option("constants", false); options.set_option("intervals", false); options.set_option("non-null", false); + options.set_option("dependence-graph", false); if(cmdline.isset("intervals") || cmdline.isset("show-intervals")) @@ -220,10 +227,13 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) options.set_option("non-null", true); else if(cmdline.isset("constants")) options.set_option("constants", true); - - if(!(options.get_bool_option("constants") || - options.get_bool_option("intervals") || - options.get_bool_option("non-null"))) + else if (cmdline.isset("dependence-graph")) + options.set_option("dependence-graph", true); + + if (!(options.get_bool_option("constants") || + options.get_bool_option("intervals") || + options.get_bool_option("non-null") || + options.get_bool_option("dependence-graph"))) { status() << "Domain defaults to --constants" << eom; options.set_option("constants", true); @@ -581,12 +591,14 @@ void goto_analyzer_parse_optionst::help() " --constants constant abstraction\n" " --intervals interval abstraction\n" " --non-null non-null abstraction\n" + " --dependence-graph dependency relation between instructions\n" "\n" "Output options:\n" " --text file_name output results in plain text to given file\n" // NOLINTNEXTLINE(whitespace/line_length) " --json file_name output results in JSON format to given file\n" " --xml file_name output results in XML format to given file\n" + " --dot file_name output results in DOT format to given file\n" "\n" "Other analyses:\n" // NOLINTNEXTLINE(whitespace/line_length) diff --git a/src/goto-analyzer/goto_analyzer_parse_options.h b/src/goto-analyzer/goto_analyzer_parse_options.h index f4330a5260f..557d733a4e9 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.h +++ b/src/goto-analyzer/goto_analyzer_parse_options.h @@ -41,12 +41,13 @@ class optionst; "(gcc)(arch):" \ "(taint):(show-taint)" \ "(show-local-may-alias)" \ - "(json):(xml):(text):" \ + "(json):(xml):(text):(dot):" \ "(unreachable-instructions)(unreachable-functions)" \ "(reachable-functions)" \ "(intervals)(show-intervals)" \ "(non-null)(show-non-null)" \ "(constants)" \ + "(dependence-graph)" \ "(show)(verify)(simplify):" \ "(flow-sensitive)(concurrent)" diff --git a/src/goto-analyzer/static_show_domain.cpp b/src/goto-analyzer/static_show_domain.cpp index a3a2616c152..7ad61565a40 100644 --- a/src/goto-analyzer/static_show_domain.cpp +++ b/src/goto-analyzer/static_show_domain.cpp @@ -14,6 +14,7 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk #include #include +#include #include "static_show_domain.h" @@ -36,18 +37,23 @@ bool static_show_domain( message_handlert &message_handler, std::ostream &out) { - ai_baset *domain=NULL; - + ai_baset *domain = NULL; + namespacet ns(goto_model.symbol_table); + if(options.get_bool_option("flow-sensitive")) { if(options.get_bool_option("constants")) - domain=new ait(); + domain = new ait(); else if(options.get_bool_option("intervals")) - domain=new ait(); + domain = new ait(); + + //else if(options.get_bool_option("non-null")) + // domain = new ait(); + + else if(options.get_bool_option("dependence-graph")) + domain = new dependence_grapht(ns); - // else if(options.get_bool_option("non-null")) - // domain=new ait(); } else if(options.get_bool_option("concurrent")) { @@ -75,10 +81,20 @@ bool static_show_domain( // status() << "Performing analysis" << eom; (*domain)(goto_model); + if(options.get_bool_option("json")) out << domain->output_json(goto_model); else if(options.get_bool_option("xml")) out << domain->output_xml(goto_model); + else if(options.get_bool_option("dot") && options.get_bool_option("dependence-graph")) + { + dependence_grapht *d = dynamic_cast(domain); + assert(d != NULL); + + out << "digraph g {\n"; + d->output_dot(out); + out << "}\n"; + } else domain->output(goto_model, out); From d0b728a5520a365ec957884e50fa4cb514456605 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 22 May 2017 20:21:09 +0100 Subject: [PATCH 010/129] Program simplification now removes unused instructions. --- .../goto_analyzer_parse_options.cpp | 2 ++ .../goto_analyzer_parse_options.h | 3 ++- src/goto-analyzer/static_simplifier.cpp | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index 9c687aabe20..ebf7049c8a7 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -194,6 +194,8 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) options.set_option("show", true); } + // For development allow slicing to be disabled in the simplify task + options.set_option("simplify-slicing", !(cmdline.isset("no-simplify-slicing"))); // Abstract interpreter choice options.set_option("flow-sensitive", false); diff --git a/src/goto-analyzer/goto_analyzer_parse_options.h b/src/goto-analyzer/goto_analyzer_parse_options.h index 557d733a4e9..6ec661093c5 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.h +++ b/src/goto-analyzer/goto_analyzer_parse_options.h @@ -49,7 +49,8 @@ class optionst; "(constants)" \ "(dependence-graph)" \ "(show)(verify)(simplify):" \ - "(flow-sensitive)(concurrent)" + "(flow-sensitive)(concurrent)" \ + "(no-simplify-slicing)" class goto_analyzer_parse_optionst: public parse_options_baset, diff --git a/src/goto-analyzer/static_simplifier.cpp b/src/goto-analyzer/static_simplifier.cpp index fe7118563e3..66797d1f11f 100644 --- a/src/goto-analyzer/static_simplifier.cpp +++ b/src/goto-analyzer/static_simplifier.cpp @@ -19,6 +19,9 @@ Author: Lucas Cordeiro, lucas.cordeiro@cs.ox.ac.uk #include #include +#include +#include + #include "static_simplifier.h" template @@ -74,6 +77,21 @@ bool static_simplifiert::operator()(void) status() << "Simplifying program" << eom; simplify_program(); + // Remove obviously unreachable things and (now) unconditional branches + if (options.get_bool_option("simplify-slicing")) + { + status() << "Removing unreachable instructions" << eom; + + remove_skip(goto_functions); // Removes goto false + goto_functions.update(); + + remove_unreachable(goto_functions); // Convert unreachable to skips + goto_functions.update(); + + remove_skip(goto_functions); // Remove all of the new skips + goto_functions.update(); + } + status() << "Writing goto binary" << eom; return write_goto_binary(out, ns.get_symbol_table(), goto_functions); } From 427580dad8297f856b7125a1c830592d581224ad Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 19 Dec 2016 19:32:54 +0000 Subject: [PATCH 011/129] Catch exceptions thrown in doit() in goto analyzer. --- .../goto_analyzer_parse_options.cpp | 335 ++++++++++-------- 1 file changed, 187 insertions(+), 148 deletions(-) diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index ebf7049c8a7..2197169b831 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -245,202 +245,241 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) /// invoke main modules int goto_analyzer_parse_optionst::doit() { - if(cmdline.isset("version")) + try { - std::cout << CBMC_VERSION << '\n'; - return 0; - } + if(cmdline.isset("version")) + { + std::cout << CBMC_VERSION << std::endl; + return 0; + } - // - // command line options - // + // + // command line options + // + optionst options; + get_command_line_options(options); + eval_verbosity(); - optionst options; - get_command_line_options(options); - eval_verbosity(); + // + // Print a banner + // + status() << "GOTO-ANALYZER version " CBMC_VERSION " " + << sizeof(void *)*8 << "-bit " + << config.this_architecture() << " " + << config.this_operating_system() << eom; - // - // Print a banner - // - status() << "GOTO-ANALYSER version " CBMC_VERSION " " - << sizeof(void *)*8 << "-bit " - << config.this_architecture() << " " - << config.this_operating_system() << eom; + register_languages(); - register_languages(); + if(initialize_goto_model(goto_model, cmdline, get_message_handler())) + return 6; + + if(process_goto_program(options)) + return 6; - if(initialize_goto_model(goto_model, cmdline, get_message_handler())) - return 6; + goto_functionst::function_mapt::const_iterator f_it= + goto_model.goto_functions.function_map.find( + goto_functionst::entry_point()); - if(process_goto_program(options)) - return 6; + if(f_it==goto_model.goto_functions.function_map.end()) + { + error() << "Entry point not found" << eom; + return 6; + } - if(cmdline.isset("taint")) - { - std::string taint_file=cmdline.get_value("taint"); + if(process_goto_program(options)) + return 6; + + status() << "Starting analysis" << eom; - if(cmdline.isset("show-taint")) + if(cmdline.isset("taint")) { - taint_analysis(goto_model, taint_file, get_message_handler(), true, ""); - return 0; + std::string taint_file=cmdline.get_value("taint"); + + if(cmdline.isset("show-taint")) + { + taint_analysis(goto_model, taint_file, get_message_handler(), true, ""); + return 0; + } + else + { + std::string json_file=cmdline.get_value("json"); + bool result=taint_analysis( + goto_model, + taint_file, + get_message_handler(), + false, + json_file); + return result?10:0; + } } - else + + if(cmdline.isset("unreachable-instructions")) { - std::string json_file=cmdline.get_value("json"); - bool result=taint_analysis( - goto_model, - taint_file, - get_message_handler(), - false, - json_file); - return result?10:0; - } - } + const std::string json_file=cmdline.get_value("json"); - if(cmdline.isset("unreachable-instructions")) - { - const std::string json_file=cmdline.get_value("json"); + if(json_file.empty()) + unreachable_instructions(goto_model, false, std::cout); + else if(json_file=="-") + unreachable_instructions(goto_model, true, std::cout); + else + { + std::ofstream ofs(json_file); + if(!ofs) + { + error() << "Failed to open json output `" + << json_file << "'" << eom; + return 6; + } + + unreachable_instructions(goto_model, true, ofs); + } - if(json_file.empty()) - unreachable_instructions(goto_model, false, std::cout); - else if(json_file=="-") - unreachable_instructions(goto_model, true, std::cout); - else + return 0; + } + + if(cmdline.isset("unreachable-functions")) { - std::ofstream ofs(json_file); - if(!ofs) + const std::string json_file=cmdline.get_value("json"); + + if(json_file.empty()) + unreachable_functions(goto_model, false, std::cout); + else if(json_file=="-") + unreachable_functions(goto_model, true, std::cout); + else { - error() << "Failed to open json output `" - << json_file << "'" << eom; - return 6; + std::ofstream ofs(json_file); + if(!ofs) + { + error() << "Failed to open json output `" + << json_file << "'" << eom; + return 6; + } + + unreachable_functions(goto_model, true, ofs); } - unreachable_instructions(goto_model, true, ofs); + return 0; } - return 0; - } + if(cmdline.isset("reachable-functions")) + { + const std::string json_file=cmdline.get_value("json"); - if(cmdline.isset("unreachable-functions")) - { - const std::string json_file=cmdline.get_value("json"); + if(json_file.empty()) + reachable_functions(goto_model, false, std::cout); + else if(json_file=="-") + reachable_functions(goto_model, true, std::cout); + else + { + std::ofstream ofs(json_file); + if(!ofs) + { + error() << "Failed to open json output `" + << json_file << "'" << eom; + return 6; + } + + reachable_functions(goto_model, true, ofs); + } - if(json_file.empty()) - unreachable_functions(goto_model, false, std::cout); - else if(json_file=="-") - unreachable_functions(goto_model, true, std::cout); - else + return 0; + } + + if(cmdline.isset("show-local-may-alias")) { - std::ofstream ofs(json_file); - if(!ofs) + namespacet ns(goto_model.symbol_table); + + forall_goto_functions(it, goto_model.goto_functions) { - error() << "Failed to open json output `" - << json_file << "'" << eom; - return 6; + std::cout << ">>>>\n"; + std::cout << ">>>> " << it->first << '\n'; + std::cout << ">>>>\n"; + local_may_aliast local_may_alias(it->second); + local_may_alias.output(std::cout, it->second, ns); + std::cout << '\n'; } - unreachable_functions(goto_model, true, ofs); + return 0; } - return 0; - } + label_properties(goto_model); - if(cmdline.isset("reachable-functions")) - { - const std::string json_file=cmdline.get_value("json"); + if(cmdline.isset("show-properties")) + { + show_properties(goto_model, get_ui()); + return 0; + } + + if(set_properties()) + return 7; - if(json_file.empty()) - reachable_functions(goto_model, false, std::cout); - else if(json_file=="-") - reachable_functions(goto_model, true, std::cout); + // Output file factory + std::ostream *out; + const std::string outfile=options.get_option("outfile"); + if(outfile=="-") + out=&std::cout; else { - std::ofstream ofs(json_file); - if(!ofs) + if(options.get_bool_option("simplify")) + out=new std::ofstream(outfile, std::ios::binary); + else + out=new std::ofstream(outfile); + + if(!*out) { - error() << "Failed to open json output `" - << json_file << "'" << eom; + error() << "Failed to open output file `" << outfile << "'" << eom; return 6; } - - reachable_functions(goto_model, true, ofs); } - return 0; - } - - if(cmdline.isset("show-local-may-alias")) - { - namespacet ns(goto_model.symbol_table); - - forall_goto_functions(it, goto_model.goto_functions) + // Run the analysis + bool result=true; + if(options.get_bool_option("show")) + result= + static_show_domain( + goto_model, + options, + get_message_handler(), + *out); + else if(options.get_bool_option("verify")) + result=static_analyzer(goto_model, options, get_message_handler(), *out); + else if(options.get_bool_option("simplify")) + result= + static_simplifier( + goto_model, + options, + get_message_handler(), + *out); + else { - std::cout << ">>>>\n"; - std::cout << ">>>> " << it->first << '\n'; - std::cout << ">>>>\n"; - local_may_aliast local_may_alias(it->second); - local_may_alias.output(std::cout, it->second, ns); - std::cout << '\n'; + error() << "No task given" << eom; + return 6; } - return 0; - } - - label_properties(goto_model); + if(out!=&std::cout) + delete out; - if(cmdline.isset("show-properties")) + return result?10:0; + } + catch(const char *e) { - show_properties(goto_model, get_ui()); - return 0; + error() << e << eom; + return 6; } - - if(set_properties()) - return 7; - - - // Output file factory - std::ostream *out; - const std::string outfile=options.get_option("outfile"); - if(outfile=="-") - out=&std::cout; - else + catch(const std::string e) { - out=new std::ofstream(outfile); - if(!*out) - { - error() << "Failed to open output file `" - << outfile << "'" << eom; - return 6; - } + error() << e << eom; + return 6; } - - - // Run the analysis - bool result=true; - if(options.get_bool_option("show")) - result=static_show_domain(goto_model, options, get_message_handler(), *out); - - else if(options.get_bool_option("verify")) - result= static_analyzer(goto_model, options, get_message_handler(), *out); - - else if(options.get_bool_option("simplify")) - result= static_simplifier(goto_model, options, get_message_handler(), *out); - else + catch(int x) + { + return x; + } + catch(std::bad_alloc) { - error() << "No task given" << eom; + error() << "Out of memory" << eom; return 6; } - - if(out!=&std::cout) - delete out; - - return result?10:0; - - - // Final defensive error case - error() << "no analysis option given -- consider reading --help" - << eom; - return 6; } bool goto_analyzer_parse_optionst::set_properties() From ce669c3e7cf870d0a082354eaa5c46301433b29c Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 22 May 2017 20:24:42 +0100 Subject: [PATCH 012/129] Fix merging issues in goto analyzer. --- src/goto-analyzer/goto_analyzer_parse_options.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index 2197169b831..67e481f91fd 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -29,6 +29,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include #include #include From 8db8121f51327873d1526410be78874e6f133101 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Wed, 25 Jan 2017 20:25:17 +0000 Subject: [PATCH 013/129] Fix whitespace to match coding guidelines --- .../goto_analyzer_parse_options.cpp | 64 ++++++++----------- src/goto-analyzer/static_analyzer.cpp | 25 ++++++-- src/goto-analyzer/static_show_domain.cpp | 24 +++---- src/goto-analyzer/static_simplifier.cpp | 45 ++++++------- 4 files changed, 76 insertions(+), 82 deletions(-) diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index 67e481f91fd..28efc4a2051 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ -Module: Goto-Analyser Command Line Option Processing +Module: Goto-Analyzer Command Line Option Processing Author: Daniel Kroening, kroening@kroening.com @@ -98,7 +98,7 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) exit(1); } - #if 0 +#if 0 if(cmdline.isset("c89")) config.ansi_c.set_c89(); @@ -116,9 +116,9 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) if(cmdline.isset("cpp11")) config.cpp.set_cpp11(); - #endif +#endif - #if 0 +#if 0 // check assertions if(cmdline.isset("no-assertions")) options.set_option("assertions", false); @@ -134,8 +134,7 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) // magic error label if(cmdline.isset("error-label")) options.set_option("error-label", cmdline.get_values("error-label")); - #endif - +#endif // Output format choice options.set_option("text", false); @@ -169,15 +168,14 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) options.set_option("text", true); } - // Task options - options.set_option( "show", false); - options.set_option( "verify", false); + options.set_option("show", false); + options.set_option("verify", false); options.set_option("simplify", false); if(cmdline.isset("show") || - cmdline.isset("show-intervals") || - cmdline.isset("show-non-null")) + cmdline.isset("show-intervals") || + cmdline.isset("show-non-null")) options.set_option("show", true); else if(cmdline.isset("verify")) options.set_option("verify", true); @@ -187,16 +185,18 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) options.set_option("outfile", cmdline.get_value("simplify")); } - if(!(options.get_bool_option("show") || - options.get_bool_option("verify") || - options.get_bool_option("simplify"))) + if(!(options.get_bool_option("show") || + options.get_bool_option("verify") || + options.get_bool_option("simplify"))) { status() << "Task defaults to --show" << eom; options.set_option("show", true); } // For development allow slicing to be disabled in the simplify task - options.set_option("simplify-slicing", !(cmdline.isset("no-simplify-slicing"))); + options.set_option( + "simplify-slicing", + !(cmdline.isset("no-simplify-slicing"))); // Abstract interpreter choice options.set_option("flow-sensitive", false); @@ -207,14 +207,7 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) else if(cmdline.isset("concurrent")) options.set_option("concurrent", true); else - { - is_threadedt is_threaded(goto_model.goto_functions); - bool contains_concurrent_code=is_threaded(); - - options.set_option("flow-sensitive", !contains_concurrent_code); - options.set_option("concurrent", contains_concurrent_code); - } - + options.set_option("flow-sensitive", true); // Domain choice options.set_option("constants", false); @@ -233,10 +226,10 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) else if (cmdline.isset("dependence-graph")) options.set_option("dependence-graph", true); - if (!(options.get_bool_option("constants") || - options.get_bool_option("intervals") || - options.get_bool_option("non-null") || - options.get_bool_option("dependence-graph"))) + if (!(options.get_bool_option("constants") || + options.get_bool_option("intervals") || + options.get_bool_option("non-null") || + options.get_bool_option("dependence-graph"))) { status() << "Domain defaults to --constants" << eom; options.set_option("constants", true); @@ -490,19 +483,16 @@ bool goto_analyzer_parse_optionst::set_properties() if(cmdline.isset("property")) ::set_properties(goto_model, cmdline.get_values("property")); } - catch(const char *e) { error() << e << eom; return true; } - catch(const std::string e) { error() << e << eom; return true; } - catch(int) { return true; @@ -571,24 +561,20 @@ bool goto_analyzer_parse_optionst::process_goto_program( return true; } } - catch(const char *e) { error() << e << eom; return true; } - catch(const std::string e) { error() << e << eom; return true; } - catch(int) { return true; } - catch(std::bad_alloc) { error() << "Out of memory" << eom; @@ -603,7 +589,7 @@ void goto_analyzer_parse_optionst::help() { std::cout << "\n" - "* * GOTO-ANALYSER " CBMC_VERSION " - Copyright (C) 2016 "; + "* * GOTO-ANALYZER " CBMC_VERSION " - Copyright (C) 2016 "; std::cout << "(" << (sizeof(void *)*8) << "-bit version)"; @@ -630,10 +616,10 @@ void goto_analyzer_parse_optionst::help() " --concurrent use concurrent abstract interpreter\n" "\n" "Domain options:\n" - " --constants constant abstraction\n" - " --intervals interval abstraction\n" - " --non-null non-null abstraction\n" - " --dependence-graph dependency relation between instructions\n" + " --constants constant domain\n" + " --intervals interval domain\n" + " --non-null non-null domain\n" + " --dependence-graph data and control dependencies between instructions\n" // NOLINT(*) "\n" "Output options:\n" " --text file_name output results in plain text to given file\n" diff --git a/src/goto-analyzer/static_analyzer.cpp b/src/goto-analyzer/static_analyzer.cpp index a9b227c62e8..aa6222da404 100644 --- a/src/goto-analyzer/static_analyzer.cpp +++ b/src/goto-analyzer/static_analyzer.cpp @@ -97,21 +97,31 @@ void static_analyzert::plain_text_report() << ']' << ' '; result() << i_it->source_location; + if(!i_it->source_location.get_comment().empty()) result() << ", " << i_it->source_location.get_comment(); + result() << ": "; + if(simplified.is_true()) - { result() << "SUCCESS"; pass++; } + { + result() << "SUCCESS"; pass++; + } else if(simplified.is_false()) - { result() << "FAILURE (if reachable)"; fail++; } + { + result() << "FAILURE (if reachable)"; fail++; + } else - { result() << "UNKNOWN"; unknown++; } - result() << eom; + { + result() << "UNKNOWN"; unknown++; + } + result() << eom; } status() << '\n'; } + status() << "SUMMARY: " << pass << " pass, " << fail << " fail if reachable, " << unknown << " unknown\n"; } @@ -191,7 +201,8 @@ void static_analyzert::xml_report() x.set_attribute("file", id2string(i_it->source_location.get_file())); x.set_attribute("line", id2string(i_it->source_location.get_line())); x.set_attribute( - "description", id2string(i_it->source_location.get_comment())); + "description", + id2string(i_it->source_location.get_comment())); } } @@ -213,11 +224,11 @@ bool static_analyzer( if(options.get_bool_option("flow-sensitive")) { if(options.get_bool_option("constants")) - return static_analyzert > + return static_analyzert> (goto_model, options, message_handler, out)(); else if(options.get_bool_option("intervals")) - return static_analyzert > + return static_analyzert> (goto_model, options, message_handler, out)(); // else if(options.get_bool_option("non-null")) diff --git a/src/goto-analyzer/static_show_domain.cpp b/src/goto-analyzer/static_show_domain.cpp index 7ad61565a40..8d24c522eb6 100644 --- a/src/goto-analyzer/static_show_domain.cpp +++ b/src/goto-analyzer/static_show_domain.cpp @@ -43,27 +43,21 @@ bool static_show_domain( if(options.get_bool_option("flow-sensitive")) { if(options.get_bool_option("constants")) - domain = new ait(); - + domain=new ait(); else if(options.get_bool_option("intervals")) - domain = new ait(); - - //else if(options.get_bool_option("non-null")) - // domain = new ait(); - + domain=new ait(); else if(options.get_bool_option("dependence-graph")) - domain = new dependence_grapht(ns); - + domain=new dependence_grapht(ns); } else if(options.get_bool_option("concurrent")) { // Constant and interval don't have merge_shared yet #if 0 if(options.get_bool_option("constants")) - domain=new concurrency_aware_ait(); + domain=new concurrency_aware_ait(); else if(options.get_bool_option("intervals")) - domain=new concurrency_aware_ait(); + domain=new concurrency_aware_ait(); // else if(options.get_bool_option("non-null")) // domain=new concurrency_aware_ait(); @@ -86,10 +80,11 @@ bool static_show_domain( out << domain->output_json(goto_model); else if(options.get_bool_option("xml")) out << domain->output_xml(goto_model); - else if(options.get_bool_option("dot") && options.get_bool_option("dependence-graph")) + else if(options.get_bool_option("dot") && + options.get_bool_option("dependence-graph")) { - dependence_grapht *d = dynamic_cast(domain); - assert(d != NULL); + dependence_grapht *d=dynamic_cast(domain); + assert(d!=NULL); out << "digraph g {\n"; d->output_dot(out); @@ -99,5 +94,6 @@ bool static_show_domain( domain->output(goto_model, out); delete domain; + return false; } diff --git a/src/goto-analyzer/static_simplifier.cpp b/src/goto-analyzer/static_simplifier.cpp index 66797d1f11f..ce5bd8c511d 100644 --- a/src/goto-analyzer/static_simplifier.cpp +++ b/src/goto-analyzer/static_simplifier.cpp @@ -14,13 +14,12 @@ Author: Lucas Cordeiro, lucas.cordeiro@cs.ox.ac.uk #include -#include - #include #include #include #include +#include #include "static_simplifier.h" @@ -64,7 +63,8 @@ Function: static_simplifiert::operator() Outputs: false on success, true on failure. - Purpose: Run the analysis, check the assertions and report in the correct format. + Purpose: Run the analysis, check the assertions and report in the + correct format. \*******************************************************************/ @@ -78,7 +78,7 @@ bool static_simplifiert::operator()(void) simplify_program(); // Remove obviously unreachable things and (now) unconditional branches - if (options.get_bool_option("simplify-slicing")) + if(options.get_bool_option("simplify-slicing")) { status() << "Removing unreachable instructions" << eom; @@ -105,7 +105,8 @@ Function: static_simplifiert::simplify_guard Outputs: 1 if simplified, 0 if not. - Purpose: Simplifies the instruction's guard using the information in the abstract domain. + Purpose: Simplifies the instruction's guard using the information in + the abstract domain. \*******************************************************************/ @@ -114,7 +115,7 @@ unsigned static_simplifiert::simplify_guard( goto_programt::instructionst::iterator &i_it) { exprt simplified=domain[i_it].domain_simplify(i_it->guard, ns); - unsigned return_value=(simplified==i_it->guard) ? 0 : 1; + unsigned return_value=(simplified==i_it->guard)?0:1; i_it->guard=simplified; return return_value; } @@ -127,7 +128,8 @@ Function: static_simplifiert::simplify_program Outputs: None. - Purpose: Simplifies the program using the information in the abstract domain. + Purpose: Simplifies the program using the information in the abstract + domain. \*******************************************************************/ @@ -173,17 +175,18 @@ void static_simplifiert::simplify_program() code_assignt assign(to_code_assign(i_it->code)); /* - ** Simplification needs to be aware of which side of the - ** expression it is handling as: - ** i=j - ** should simplify to i=1, not to 0=1. + Simplification needs to be aware of which side of the + expression it is handling as: + i=j + should simplify to i=1, not to 0=1. */ exprt simp_lhs=domain[i_it].domain_simplify(assign.lhs(), ns, true); exprt simp_rhs=domain[i_it].domain_simplify(assign.rhs(), ns, false); unsigned result=(simp_lhs==assign.lhs() && - simp_rhs==assign.rhs()) ? 0 : 1; + simp_rhs==assign.rhs())?0:1; + simplified.assigns+=result; unmodified.assigns+=(1-result); @@ -222,7 +225,6 @@ void static_simplifiert::simplify_program() // Make sure the references are correct. goto_functions.update(); - status() << "SIMPLIFIED: " << " assert: " << simplified.asserts << ", assume: " << simplified.assumes @@ -241,15 +243,12 @@ void static_simplifiert::simplify_program() return; } - - - /*******************************************************************\ Function: static_simplifier - Inputs: The goto_model to analyze and simplify, options giving the domain, - the message handler and output stream. + Inputs: The goto_model to analyze and simplify, options giving the + domain, the message handler and output stream. Outputs: The simplified goto binary via out. @@ -266,11 +265,11 @@ bool static_simplifier( if(options.get_bool_option("flow-sensitive")) { if(options.get_bool_option("constants")) - return static_simplifiert > + return static_simplifiert> (goto_model, options, message_handler, out)(); else if(options.get_bool_option("intervals")) - return static_simplifiert > + return static_simplifiert> (goto_model, options, message_handler, out)(); // else if(options.get_bool_option("non-null")) @@ -282,8 +281,9 @@ bool static_simplifier( // Constant and interval don't have merge_shared yet #if 0 if(options.get_bool_option("constants")) - return static_simplifiert > - (goto_model, options, message_handler, out)(); + return static_simplifiert< + concurrency_aware_ait> + (goto_model, options, message_handler, out)(); else if(options.get_bool_option("intervals")) return static_simplifiert > @@ -298,5 +298,6 @@ bool static_simplifier( messaget m(message_handler); m.status() << "Task / Interpreter / Domain combination not supported" << messaget::eom; + return true; } From 7193056055d863ee044663645fd63520b4a36a81 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 23 May 2017 00:02:05 +0100 Subject: [PATCH 014/129] Whitespace fixes in goto-analyzer. --- src/goto-analyzer/goto_analyzer_parse_options.cpp | 8 ++++---- src/goto-analyzer/static_analyzer.cpp | 9 ++++++--- src/goto-analyzer/static_show_domain.cpp | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index 28efc4a2051..1619e568bbd 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -158,7 +158,7 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) options.set_option("xml", true); options.set_option("outfile", cmdline.get_value("xml")); } - else if (cmdline.isset("dot")) + else if(cmdline.isset("dot")) { options.set_option("dot", true); options.set_option("outfile", cmdline.get_value("dot")); @@ -223,10 +223,10 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) options.set_option("non-null", true); else if(cmdline.isset("constants")) options.set_option("constants", true); - else if (cmdline.isset("dependence-graph")) + else if(cmdline.isset("dependence-graph")) options.set_option("dependence-graph", true); - - if (!(options.get_bool_option("constants") || + + if(!(options.get_bool_option("constants") || options.get_bool_option("intervals") || options.get_bool_option("non-null") || options.get_bool_option("dependence-graph"))) diff --git a/src/goto-analyzer/static_analyzer.cpp b/src/goto-analyzer/static_analyzer.cpp index aa6222da404..960bedd3f12 100644 --- a/src/goto-analyzer/static_analyzer.cpp +++ b/src/goto-analyzer/static_analyzer.cpp @@ -240,8 +240,9 @@ bool static_analyzer( // Constant and interval don't have merge_shared yet #if 0 if(options.get_bool_option("constants")) - return static_analyzert > - (goto_model, options, message_handler, out)(); + return static_analyzert> + (goto_model, options, message_handler, out)(); else if(options.get_bool_option("intervals")) return static_analyzert > @@ -254,6 +255,8 @@ bool static_analyzer( } messaget m(message_handler); - m.status() << "Task / Interpreter / Domain combination not supported" << messaget::eom; + m.status() << "Task / Interpreter / Domain combination not supported" + << messaget::eom; + return true; } diff --git a/src/goto-analyzer/static_show_domain.cpp b/src/goto-analyzer/static_show_domain.cpp index 8d24c522eb6..412c45e2bc2 100644 --- a/src/goto-analyzer/static_show_domain.cpp +++ b/src/goto-analyzer/static_show_domain.cpp @@ -39,7 +39,7 @@ bool static_show_domain( { ai_baset *domain = NULL; namespacet ns(goto_model.symbol_table); - + if(options.get_bool_option("flow-sensitive")) { if(options.get_bool_option("constants")) From cb54f29df3f24328508862381748a1496078dde7 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Fri, 3 Feb 2017 12:33:14 +0000 Subject: [PATCH 015/129] regression test changes --- .../{constant_propagation1.c => main.c} | 0 .../constant_propagation_01/test.desc | 10 +-- .../{constant_propagation_02.c => main.c} | 0 .../constant_propagation_02/original | 3 - .../constant_propagation_02/simplified | 81 ------------------- .../constant_propagation_02/test.desc | 10 +-- .../{constant_propagation_03.c => main.c} | 0 .../constant_propagation_03/test.desc | 8 +- .../{constant_propagation_04.c => main.c} | 0 .../constant_propagation_04/test.desc | 8 +- .../{constant_propagation_05.c => main.c} | 0 .../constant_propagation_05/test.desc | 4 +- .../main.c} | 0 .../constant_propagation_06/test.desc | 15 +--- .../main.c} | 0 .../constant_propagation_07/test.desc | 7 +- .../main.c} | 0 .../constant_propagation_08/test.desc | 9 +-- .../main.c} | 0 .../constant_propagation_09/test.desc | 8 +- .../main.c} | 0 .../constant_propagation_10/test.desc | 7 +- .../main.c} | 0 .../constant_propagation_11/test.desc | 8 +- .../main.c} | 0 .../constant_propagation_12/test.desc | 8 +- .../main.c} | 0 .../constant_propagation_13/test.desc | 4 +- .../main.c} | 0 .../constant_propagation_14/test.desc | 8 +- .../main.c} | 0 .../constant_propagation_15/test.desc | 7 +- .../constant_propagation_16/test.desc | 8 -- .../constant_propagation_17/test.desc | 9 --- .../constant_propagation_18/test.desc | 8 -- regression/goto-analyzer/intervals1/test.desc | 15 ---- .../goto-analyzer/intervals10/test.desc | 12 --- .../goto-analyzer/intervals11/test.desc | 9 --- .../goto-analyzer/intervals12/test.desc | 9 --- regression/goto-analyzer/intervals2/test.desc | 8 -- regression/goto-analyzer/intervals3/test.desc | 8 -- regression/goto-analyzer/intervals4/test.desc | 8 -- regression/goto-analyzer/intervals5/test.desc | 8 -- regression/goto-analyzer/intervals6/test.desc | 8 -- regression/goto-analyzer/intervals7/test.desc | 8 -- regression/goto-analyzer/intervals8/test.desc | 8 -- regression/goto-analyzer/intervals9/test.desc | 8 -- .../intervals1.c => intervals_01/main.c} | 2 +- .../goto-analyzer/intervals_01/test.desc | 15 ++++ .../intervals2.c => intervals_02/main.c} | 2 - .../goto-analyzer/intervals_02/test.desc | 8 ++ .../intervals3.c => intervals_03/main.c} | 0 .../goto-analyzer/intervals_03/test.desc | 8 ++ .../intervals4.c => intervals_04/main.c} | 0 .../goto-analyzer/intervals_04/test.desc | 8 ++ .../intervals5.c => intervals_05/main.c} | 0 .../goto-analyzer/intervals_05/test.desc | 8 ++ .../intervals6.c => intervals_06/main.c} | 0 .../goto-analyzer/intervals_06/test.desc | 8 ++ .../intervals7.c => intervals_07/main.c} | 0 .../goto-analyzer/intervals_07/test.desc | 8 ++ .../intervals8.c => intervals_08/main.c} | 0 .../goto-analyzer/intervals_08/test.desc | 8 ++ .../intervals9.c => intervals_09/main.c} | 0 .../goto-analyzer/intervals_09/test.desc | 8 ++ .../intervals10.c => intervals_10/main.c} | 0 .../goto-analyzer/intervals_10/test.desc | 12 +++ .../intervals11.c => intervals_11/main.c} | 0 .../goto-analyzer/intervals_11/test.desc | 9 +++ .../intervals12.c => intervals_12/main.c} | 0 .../goto-analyzer/intervals_12/test.desc | 9 +++ .../main.c} | 0 .../goto-analyzer/intervals_13/test.desc | 15 ++++ .../main.c} | 0 .../goto-analyzer/intervals_14/test.desc | 10 +++ .../main.c} | 0 .../goto-analyzer/intervals_15/test.desc | 8 ++ 77 files changed, 199 insertions(+), 286 deletions(-) rename regression/goto-analyzer/constant_propagation_01/{constant_propagation1.c => main.c} (100%) rename regression/goto-analyzer/constant_propagation_02/{constant_propagation_02.c => main.c} (100%) delete mode 100644 regression/goto-analyzer/constant_propagation_02/original delete mode 100644 regression/goto-analyzer/constant_propagation_02/simplified rename regression/goto-analyzer/constant_propagation_03/{constant_propagation_03.c => main.c} (100%) rename regression/goto-analyzer/constant_propagation_04/{constant_propagation_04.c => main.c} (100%) rename regression/goto-analyzer/constant_propagation_05/{constant_propagation_05.c => main.c} (100%) rename regression/goto-analyzer/{constant_propagation_07/constant_propagation_07.c => constant_propagation_06/main.c} (100%) rename regression/goto-analyzer/{constant_propagation_10/constant_propagation_10.c => constant_propagation_07/main.c} (100%) rename regression/goto-analyzer/{constant_propagation_11/constant_propagation_11.c => constant_propagation_08/main.c} (100%) rename regression/goto-analyzer/{constant_propagation_12/constant_propagation_12.c => constant_propagation_09/main.c} (100%) rename regression/goto-analyzer/{constant_propagation_13/constant_propagation_13.c => constant_propagation_10/main.c} (100%) rename regression/goto-analyzer/{constant_propagation_14/constant_propagation_14.c => constant_propagation_11/main.c} (100%) rename regression/goto-analyzer/{constant_propagation_15/constant_propagation_15.c => constant_propagation_12/main.c} (100%) rename regression/goto-analyzer/{constant_propagation_16/constant_propagation_16.c => constant_propagation_13/main.c} (100%) rename regression/goto-analyzer/{constant_propagation_17/constant_propagation_17.c => constant_propagation_14/main.c} (100%) rename regression/goto-analyzer/{constant_propagation_18/constant_propagation_18.c => constant_propagation_15/main.c} (100%) delete mode 100644 regression/goto-analyzer/constant_propagation_16/test.desc delete mode 100644 regression/goto-analyzer/constant_propagation_17/test.desc delete mode 100644 regression/goto-analyzer/constant_propagation_18/test.desc delete mode 100644 regression/goto-analyzer/intervals1/test.desc delete mode 100644 regression/goto-analyzer/intervals10/test.desc delete mode 100644 regression/goto-analyzer/intervals11/test.desc delete mode 100644 regression/goto-analyzer/intervals12/test.desc delete mode 100644 regression/goto-analyzer/intervals2/test.desc delete mode 100644 regression/goto-analyzer/intervals3/test.desc delete mode 100644 regression/goto-analyzer/intervals4/test.desc delete mode 100644 regression/goto-analyzer/intervals5/test.desc delete mode 100644 regression/goto-analyzer/intervals6/test.desc delete mode 100644 regression/goto-analyzer/intervals7/test.desc delete mode 100644 regression/goto-analyzer/intervals8/test.desc delete mode 100644 regression/goto-analyzer/intervals9/test.desc rename regression/goto-analyzer/{intervals1/intervals1.c => intervals_01/main.c} (99%) create mode 100644 regression/goto-analyzer/intervals_01/test.desc rename regression/goto-analyzer/{intervals2/intervals2.c => intervals_02/main.c} (80%) create mode 100644 regression/goto-analyzer/intervals_02/test.desc rename regression/goto-analyzer/{intervals3/intervals3.c => intervals_03/main.c} (100%) create mode 100644 regression/goto-analyzer/intervals_03/test.desc rename regression/goto-analyzer/{intervals4/intervals4.c => intervals_04/main.c} (100%) create mode 100644 regression/goto-analyzer/intervals_04/test.desc rename regression/goto-analyzer/{intervals5/intervals5.c => intervals_05/main.c} (100%) create mode 100644 regression/goto-analyzer/intervals_05/test.desc rename regression/goto-analyzer/{intervals6/intervals6.c => intervals_06/main.c} (100%) create mode 100644 regression/goto-analyzer/intervals_06/test.desc rename regression/goto-analyzer/{intervals7/intervals7.c => intervals_07/main.c} (100%) create mode 100644 regression/goto-analyzer/intervals_07/test.desc rename regression/goto-analyzer/{intervals8/intervals8.c => intervals_08/main.c} (100%) create mode 100644 regression/goto-analyzer/intervals_08/test.desc rename regression/goto-analyzer/{intervals9/intervals9.c => intervals_09/main.c} (100%) create mode 100644 regression/goto-analyzer/intervals_09/test.desc rename regression/goto-analyzer/{intervals10/intervals10.c => intervals_10/main.c} (100%) create mode 100644 regression/goto-analyzer/intervals_10/test.desc rename regression/goto-analyzer/{intervals11/intervals11.c => intervals_11/main.c} (100%) create mode 100644 regression/goto-analyzer/intervals_11/test.desc rename regression/goto-analyzer/{intervals12/intervals12.c => intervals_12/main.c} (100%) create mode 100644 regression/goto-analyzer/intervals_12/test.desc rename regression/goto-analyzer/{constant_propagation_06/constant_propagation_06.c => intervals_13/main.c} (100%) create mode 100644 regression/goto-analyzer/intervals_13/test.desc rename regression/goto-analyzer/{constant_propagation_08/constant_propagation_08.c => intervals_14/main.c} (100%) create mode 100644 regression/goto-analyzer/intervals_14/test.desc rename regression/goto-analyzer/{constant_propagation_09/constant_propagation_09.c => intervals_15/main.c} (100%) create mode 100644 regression/goto-analyzer/intervals_15/test.desc diff --git a/regression/goto-analyzer/constant_propagation_01/constant_propagation1.c b/regression/goto-analyzer/constant_propagation_01/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_01/constant_propagation1.c rename to regression/goto-analyzer/constant_propagation_01/main.c diff --git a/regression/goto-analyzer/constant_propagation_01/test.desc b/regression/goto-analyzer/constant_propagation_01/test.desc index 1eb849c3c7a..f5aa9da5608 100644 --- a/regression/goto-analyzer/constant_propagation_01/test.desc +++ b/regression/goto-analyzer/constant_propagation_01/test.desc @@ -1,9 +1,9 @@ -FUTURE -constant_propagation1.c ---constants --simplify out.goto +CORE +main.c +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^SIMPLIFIED: assert: 1, assume: 0, goto: 2, assigns: 5, function calls: 0$ -^UNMODIFIED: assert: 0, assume: 0, goto: 0, assigns: 12, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 2, assigns: 5, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 12, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_02/constant_propagation_02.c b/regression/goto-analyzer/constant_propagation_02/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_02/constant_propagation_02.c rename to regression/goto-analyzer/constant_propagation_02/main.c diff --git a/regression/goto-analyzer/constant_propagation_02/original b/regression/goto-analyzer/constant_propagation_02/original deleted file mode 100644 index 13a9e245c81..00000000000 --- a/regression/goto-analyzer/constant_propagation_02/original +++ /dev/null @@ -1,3 +0,0 @@ -Task defaults to --show -Domain defaults to --constants -GOTO-ANALYSER version 5.5 64-bit x86_64 linux diff --git a/regression/goto-analyzer/constant_propagation_02/simplified b/regression/goto-analyzer/constant_propagation_02/simplified deleted file mode 100644 index 6c722a607de..00000000000 --- a/regression/goto-analyzer/constant_propagation_02/simplified +++ /dev/null @@ -1,81 +0,0 @@ -Reading GOTO program from `out.goto' -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -main /* main */ - // 0 file constant_propagation_02.c line 5 function main - signed int i; - // 1 file constant_propagation_02.c line 5 function main - i = 0; - // 2 file constant_propagation_02.c line 5 function main - signed int j; - // 3 file constant_propagation_02.c line 5 function main - j = 2; - // 4 file constant_propagation_02.c line 7 function main - IF FALSE THEN GOTO 1 - // 5 file constant_propagation_02.c line 9 function main - 0 = 1; - // 6 file constant_propagation_02.c line 10 function main - 2 = 3; - // 7 no location - 1: SKIP - // 8 file constant_propagation_02.c line 12 function main - ASSERT FALSE // assertion j!=3 - // 9 file constant_propagation_02.c line 12 function main - GOTO 2 - // 10 file constant_propagation_02.c line 12 function main - (void)0; - // 11 no location - 2: SKIP - // 12 file constant_propagation_02.c line 13 function main - dead j; - // 13 file constant_propagation_02.c line 13 function main - dead i; - // 14 file constant_propagation_02.c line 13 function main - main#return_value = NONDET(signed int); - // 15 file constant_propagation_02.c line 13 function main - END_FUNCTION -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -_start /* _start */ - // 16 no location - __CPROVER_initialize(); - // 17 file constant_propagation_02.c line 3 - main(); - // 18 file constant_propagation_02.c line 3 - return' = main#return_value; - // 19 file constant_propagation_02.c line 3 - dead main#return_value; - // 20 file constant_propagation_02.c line 3 - OUTPUT("return", return'); - // 21 no location - END_FUNCTION -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -__CPROVER_initialize /* __CPROVER_initialize */ - // 22 no location - // Labels: __CPROVER_HIDE - SKIP - // 23 file line 39 - __CPROVER_dead_object = NULL; - // 24 file line 38 - __CPROVER_deallocated = NULL; - // 25 file line 42 - __CPROVER_malloc_is_new_array = FALSE; - // 26 file line 40 - __CPROVER_malloc_object = NULL; - // 27 file line 41 - __CPROVER_malloc_size = 0ul; - // 28 file line 43 - __CPROVER_memory_leak = NULL; - // 29 file line 31 - __CPROVER_next_thread_id = 0ul; - // 30 file line 85 - __CPROVER_pipe_count = 0u; - // 31 file line 65 - __CPROVER_rounding_mode = 0; - // 32 file line 29 - __CPROVER_thread_id = 0ul; - // 33 file line 30 - __CPROVER_threads_exited = ARRAY_OF(FALSE); - // 34 no location - END_FUNCTION diff --git a/regression/goto-analyzer/constant_propagation_02/test.desc b/regression/goto-analyzer/constant_propagation_02/test.desc index 20cc5fcf86e..a7074d70c31 100644 --- a/regression/goto-analyzer/constant_propagation_02/test.desc +++ b/regression/goto-analyzer/constant_propagation_02/test.desc @@ -1,9 +1,9 @@ -FUTURE -constant_propagation_02.c ---constants --simplify out.goto +CORE +main.c +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^SIMPLIFIED: assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$ -^UNMODIFIED: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_03/constant_propagation_03.c b/regression/goto-analyzer/constant_propagation_03/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_03/constant_propagation_03.c rename to regression/goto-analyzer/constant_propagation_03/main.c diff --git a/regression/goto-analyzer/constant_propagation_03/test.desc b/regression/goto-analyzer/constant_propagation_03/test.desc index 2225c1a666e..ffe6d41d638 100644 --- a/regression/goto-analyzer/constant_propagation_03/test.desc +++ b/regression/goto-analyzer/constant_propagation_03/test.desc @@ -1,9 +1,9 @@ FUTURE -constant_propagation_03.c ---constants --simplify out.goto +main.c +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^SIMPLIFIED: assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$ -^UNMODIFIED: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_04/constant_propagation_04.c b/regression/goto-analyzer/constant_propagation_04/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_04/constant_propagation_04.c rename to regression/goto-analyzer/constant_propagation_04/main.c diff --git a/regression/goto-analyzer/constant_propagation_04/test.desc b/regression/goto-analyzer/constant_propagation_04/test.desc index 2510b3f8a5e..ffe6d41d638 100644 --- a/regression/goto-analyzer/constant_propagation_04/test.desc +++ b/regression/goto-analyzer/constant_propagation_04/test.desc @@ -1,9 +1,9 @@ FUTURE -constant_propagation_04.c ---constants --simplify out.goto +main.c +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^SIMPLIFIED: assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$ -^UNMODIFIED: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_05/constant_propagation_05.c b/regression/goto-analyzer/constant_propagation_05/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_05/constant_propagation_05.c rename to regression/goto-analyzer/constant_propagation_05/main.c diff --git a/regression/goto-analyzer/constant_propagation_05/test.desc b/regression/goto-analyzer/constant_propagation_05/test.desc index ddb22cc3616..e84fdb08b4f 100644 --- a/regression/goto-analyzer/constant_propagation_05/test.desc +++ b/regression/goto-analyzer/constant_propagation_05/test.desc @@ -1,8 +1,8 @@ FUTURE -constant_propagation_05.c +main.c --constants --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file constant_propagation_05.c line 12 function main, assertion j!=3: FAILURE (if reachable)$ +^\[main.assertion.1\] file main.c line 12 function main, assertion j!=3: Failure (if reachable)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_07/constant_propagation_07.c b/regression/goto-analyzer/constant_propagation_06/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_07/constant_propagation_07.c rename to regression/goto-analyzer/constant_propagation_06/main.c diff --git a/regression/goto-analyzer/constant_propagation_06/test.desc b/regression/goto-analyzer/constant_propagation_06/test.desc index 2c2596fe092..da9d7778bbf 100644 --- a/regression/goto-analyzer/constant_propagation_06/test.desc +++ b/regression/goto-analyzer/constant_propagation_06/test.desc @@ -1,15 +1,8 @@ -FUTURE -constant_propagation_06.c ---intervals --verify +CORE +main.c +--constants --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file constant_propagation_06.c line 8 function main, assertion i>=10: SUCCESS$ -^\[main.assertion.2\] file constant_propagation_06.c line 11 function main, assertion i!=30: SUCCESS$ -^\[main.assertion.3\] file constant_propagation_06.c line 14 function main, assertion i!=15: UNKNOWN$ -^\[main.assertion.4\] file constant_propagation_06.c line 17 function main, assertion 0: SUCCESS$ -^\[main.assertion.5\] file constant_propagation_06.c line 20 function main, assertion j>=10: SUCCESS$ -^\[main.assertion.6\] file constant_propagation_06.c line 23 function main, assertion i>=j: UNKNOWN$ -^\[main.assertion.7\] file constant_propagation_06.c line 26 function main, assertion i>=11: SUCCESS$ -^\[main.assertion.8\] file constant_propagation_06.c line 29 function main, assertion j<100: SUCCESS$ +^\[main.assertion.1\] file main.c line 12 function main, assertion i<51: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_10/constant_propagation_10.c b/regression/goto-analyzer/constant_propagation_07/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_10/constant_propagation_10.c rename to regression/goto-analyzer/constant_propagation_07/main.c diff --git a/regression/goto-analyzer/constant_propagation_07/test.desc b/regression/goto-analyzer/constant_propagation_07/test.desc index 615893d4f78..c4b03cd8738 100644 --- a/regression/goto-analyzer/constant_propagation_07/test.desc +++ b/regression/goto-analyzer/constant_propagation_07/test.desc @@ -1,8 +1,9 @@ FUTURE -constant_propagation_07.c ---constants --verify +main.c +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file constant_propagation_07.c line 12 function main, assertion i<51: UNKNOWN$ +^Simplified: assert: 1, assume: 0, goto: 4, assigns: 10, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 10, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_11/constant_propagation_11.c b/regression/goto-analyzer/constant_propagation_08/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_11/constant_propagation_11.c rename to regression/goto-analyzer/constant_propagation_08/main.c diff --git a/regression/goto-analyzer/constant_propagation_08/test.desc b/regression/goto-analyzer/constant_propagation_08/test.desc index 994c2c532df..07a97596c15 100644 --- a/regression/goto-analyzer/constant_propagation_08/test.desc +++ b/regression/goto-analyzer/constant_propagation_08/test.desc @@ -1,10 +1,9 @@ FUTURE -constant_propagation_08.c ---intervals --verify +main.c +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file constant_propagation_08.c line 12 function main, assertion i<50: UNKNOWN$ -^\[main.assertion.2\] file constant_propagation_08.c line 13 function main, assertion i<51: UNKNOWN$ -^\[main.assertion.3\] file constant_propagation_08.c line 14 function main, assertion i<52: SUCCESS$ +^Simplified: assert: 1, assume: 0, goto: 2, assigns: 5, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 4, assigns: 13, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_12/constant_propagation_12.c b/regression/goto-analyzer/constant_propagation_09/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_12/constant_propagation_12.c rename to regression/goto-analyzer/constant_propagation_09/main.c diff --git a/regression/goto-analyzer/constant_propagation_09/test.desc b/regression/goto-analyzer/constant_propagation_09/test.desc index 6a1b75f0c1b..eebfe27dd49 100644 --- a/regression/goto-analyzer/constant_propagation_09/test.desc +++ b/regression/goto-analyzer/constant_propagation_09/test.desc @@ -1,9 +1,9 @@ FUTURE -constant_propagation_09.c ---intervals --verify +main.c +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -******** Function main -^\[main.assertion.1\] file constant_propagation_09.c line 12 function main, assertion j<52: UNKNOWN$ +^Simplified: assert: 1, assume: 0, goto: 3, assigns: 4, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_13/constant_propagation_13.c b/regression/goto-analyzer/constant_propagation_10/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_13/constant_propagation_13.c rename to regression/goto-analyzer/constant_propagation_10/main.c diff --git a/regression/goto-analyzer/constant_propagation_10/test.desc b/regression/goto-analyzer/constant_propagation_10/test.desc index 52d98cb611b..527325b84bb 100644 --- a/regression/goto-analyzer/constant_propagation_10/test.desc +++ b/regression/goto-analyzer/constant_propagation_10/test.desc @@ -1,9 +1,8 @@ FUTURE -constant_propagation_10.c ---constants --simplify out.goto +main.c +--constants --verify ^EXIT=0$ ^SIGNAL=0$ -^SIMPLIFIED: assert: 1, assume: 0, goto: 4, assigns: 10, function calls: 0$ -^UNMODIFIED: assert: 0, assume: 0, goto: 1, assigns: 10, function calls: 2$ +^\[main.assertion.1\] file main.c line 10 function main, assertion a\[0\]==2: Failure$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_14/constant_propagation_14.c b/regression/goto-analyzer/constant_propagation_11/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_14/constant_propagation_14.c rename to regression/goto-analyzer/constant_propagation_11/main.c diff --git a/regression/goto-analyzer/constant_propagation_11/test.desc b/regression/goto-analyzer/constant_propagation_11/test.desc index 7c849326cf6..4e9c8715429 100644 --- a/regression/goto-analyzer/constant_propagation_11/test.desc +++ b/regression/goto-analyzer/constant_propagation_11/test.desc @@ -1,9 +1,9 @@ FUTURE -constant_propagation_11.c ---constants --simplify out.goto +main.c +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^SIMPLIFIED: assert: 1, assume: 0, goto: 2, assigns: 5, function calls: 0$ -^UNMODIFIED: assert: 0, assume: 0, goto: 4, assigns: 13, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_15/constant_propagation_15.c b/regression/goto-analyzer/constant_propagation_12/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_15/constant_propagation_15.c rename to regression/goto-analyzer/constant_propagation_12/main.c diff --git a/regression/goto-analyzer/constant_propagation_12/test.desc b/regression/goto-analyzer/constant_propagation_12/test.desc index ca5803363ad..208b235ccd5 100644 --- a/regression/goto-analyzer/constant_propagation_12/test.desc +++ b/regression/goto-analyzer/constant_propagation_12/test.desc @@ -1,9 +1,9 @@ FUTURE -constant_propagation_12.c ---constants --simplify out.goto +main.c +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^SIMPLIFIED: assert: 1, assume: 0, goto: 3, assigns: 4, function calls: 0$ -^UNMODIFIED: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 4, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 2, assigns: 11, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_16/constant_propagation_16.c b/regression/goto-analyzer/constant_propagation_13/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_16/constant_propagation_16.c rename to regression/goto-analyzer/constant_propagation_13/main.c diff --git a/regression/goto-analyzer/constant_propagation_13/test.desc b/regression/goto-analyzer/constant_propagation_13/test.desc index 22f10d125e3..2d2e078a424 100644 --- a/regression/goto-analyzer/constant_propagation_13/test.desc +++ b/regression/goto-analyzer/constant_propagation_13/test.desc @@ -1,8 +1,8 @@ FUTURE -constant_propagation_13.c +main.c --constants --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file constant_propagation_13.c line 10 function main, assertion a\[0\]==2: FAILURE$ +^\[main.assertion.1\] file main.c line 9 function main, assertion y==0: Failure (if reachable)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_17/constant_propagation_17.c b/regression/goto-analyzer/constant_propagation_14/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_17/constant_propagation_17.c rename to regression/goto-analyzer/constant_propagation_14/main.c diff --git a/regression/goto-analyzer/constant_propagation_14/test.desc b/regression/goto-analyzer/constant_propagation_14/test.desc index a39a1f66cda..fc3be910670 100644 --- a/regression/goto-analyzer/constant_propagation_14/test.desc +++ b/regression/goto-analyzer/constant_propagation_14/test.desc @@ -1,9 +1,9 @@ FUTURE -constant_propagation_14.c ---constants --simplify out.goto +main.c +--constants --verify ^EXIT=0$ ^SIGNAL=0$ -^SIMPLIFIED: assert: 1, assume: 0, goto: 0$ -^UNKNOWN: assert: 0, assume: 0, goto: 0$ +^\[main.assertion.1\] file main.c line 11 function main, assertion a\[0\]==1 || a\[0\]==2: Success$ +^\[main.assertion.2\] file main.c line 12 function main, assertion a\[0\]==1 && a\[0\]==2: Failure$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_18/constant_propagation_18.c b/regression/goto-analyzer/constant_propagation_15/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_18/constant_propagation_18.c rename to regression/goto-analyzer/constant_propagation_15/main.c diff --git a/regression/goto-analyzer/constant_propagation_15/test.desc b/regression/goto-analyzer/constant_propagation_15/test.desc index 20d36183eb0..aba11ba0c06 100644 --- a/regression/goto-analyzer/constant_propagation_15/test.desc +++ b/regression/goto-analyzer/constant_propagation_15/test.desc @@ -1,9 +1,8 @@ FUTURE -constant_propagation_15.c ---constants --simplify out.goto +main.c +--constants --verify ^EXIT=0$ ^SIGNAL=0$ -^SIMPLIFIED: assert: 1, assume: 0, goto: 1, assigns: 4, function calls: 0$ -^UNMODIFIED: assert: 0, assume: 0, goto: 2, assigns: 11, function calls: 2$ +^\[main.assertion.1\] file main.c line 9 function main, assertion a\[0\]==2: Failure$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_16/test.desc b/regression/goto-analyzer/constant_propagation_16/test.desc deleted file mode 100644 index b56c871deb4..00000000000 --- a/regression/goto-analyzer/constant_propagation_16/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -constant_propagation_16.c ---constants --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file constant_propagation_16.c line 9 function main, assertion y==0: FAILURE (if reachable)$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_17/test.desc b/regression/goto-analyzer/constant_propagation_17/test.desc deleted file mode 100644 index acecb91eb0a..00000000000 --- a/regression/goto-analyzer/constant_propagation_17/test.desc +++ /dev/null @@ -1,9 +0,0 @@ -FUTURE -constant_propagation_17.c ---constants --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file constant_propagation_17.c line 11 function main, assertion a\[0\]==1 || a\[0\]==2: SUCCESS$ -^\[main.assertion.2\] file constant_propagation_17.c line 12 function main, assertion a\[0\]==1 && a\[0\]==2: FAILURE$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_18/test.desc b/regression/goto-analyzer/constant_propagation_18/test.desc deleted file mode 100644 index 7ea74c4d264..00000000000 --- a/regression/goto-analyzer/constant_propagation_18/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -constant_propagation_18.c ---constants --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file constant_propagation_18.c line 9 function main, assertion a\[0\]==2: FAILURE$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/intervals1/test.desc b/regression/goto-analyzer/intervals1/test.desc deleted file mode 100644 index 5a9802eeb20..00000000000 --- a/regression/goto-analyzer/intervals1/test.desc +++ /dev/null @@ -1,15 +0,0 @@ -KNOWNBUG -intervals1.c ---intervals --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file intervals1.c line 8 function main, assertion i>=10: SUCCESS$ -^\[main.assertion.2\] file intervals1.c line 11 function main, assertion i!=30: SUCCESS$ -^\[main.assertion.3\] file intervals1.c line 14 function main, assertion i!=15: UNKNOWN$ -^\[main.assertion.4\] file intervals1.c line 17 function main, assertion 0: SUCCESS$ -^\[main.assertion.5\] file intervals1.c line 20 function main, assertion j>=10: SUCCESS$ -^\[main.assertion.6\] file intervals1.c line 23 function main, assertion i>=j: UNKNOWN$ -^\[main.assertion.7\] file intervals1.c line 26 function main, assertion i>=11: SUCCESS$ -^\[main.assertion.8\] file intervals1.c line 29 function main, assertion j<100: SUCCESS$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/intervals10/test.desc b/regression/goto-analyzer/intervals10/test.desc deleted file mode 100644 index 794198505f1..00000000000 --- a/regression/goto-analyzer/intervals10/test.desc +++ /dev/null @@ -1,12 +0,0 @@ -FUTURE -intervals10.c ---intervals --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file intervals10.c line 8 function main, assertion j<=100: SUCCESS$ -^\[main.assertion.2\] file intervals10.c line 11 function main, assertion j<101: SUCCESS$ -^\[main.assertion.3\] file intervals10.c line 14 function main, assertion j>100: FAILURE (if reachable)$ -^\[main.assertion.4\] file intervals10.c line 17 function main, assertion j<99: UNKNOWN$ -^\[main.assertion.5\] file intervals10.c line 20 function main, assertion j==100: FAILURE (if reachable)$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/intervals11/test.desc b/regression/goto-analyzer/intervals11/test.desc deleted file mode 100644 index 039cbffbeb0..00000000000 --- a/regression/goto-analyzer/intervals11/test.desc +++ /dev/null @@ -1,9 +0,0 @@ -FUTURE -intervals11.c ---intervals --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file intervals11.c line 30 function main, assertion y\[i\]>=-1.0f && y\[i\]<=1.0f: UNKNOWN$ -^\[main.assertion.2\] file intervals11.c line 35 function main, assertion y\[i\]>=-1.0f && y\[i\]<=1.0f: UNKNOWN$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/intervals12/test.desc b/regression/goto-analyzer/intervals12/test.desc deleted file mode 100644 index 59a724c28b5..00000000000 --- a/regression/goto-analyzer/intervals12/test.desc +++ /dev/null @@ -1,9 +0,0 @@ -FUTURE -intervals12.c ---intervals --verify -^EXIT=0$ -^SIGNAL=0$ -^[main.assertion.1] file intervals12.c line 8 function main, assertion j < 0: SUCCESS$ -^[main.assertion.2] file intervals12.c line 11 function main, assertion j < 0: SUCCESS$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/intervals2/test.desc b/regression/goto-analyzer/intervals2/test.desc deleted file mode 100644 index 65aae030db1..00000000000 --- a/regression/goto-analyzer/intervals2/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -KNOWNBUG -intervals2.c ---intervals --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file intervals2.c line 7 function main, assertion x > -10 && x < 100: SUCCESS$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/intervals3/test.desc b/regression/goto-analyzer/intervals3/test.desc deleted file mode 100644 index 69ded2182ee..00000000000 --- a/regression/goto-analyzer/intervals3/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -KNOWNBUG -intervals3.c ---intervals --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file intervals3.c line 7 function main, assertion x > -10 || x < 100: SUCCESS$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/intervals4/test.desc b/regression/goto-analyzer/intervals4/test.desc deleted file mode 100644 index 2b725180e3f..00000000000 --- a/regression/goto-analyzer/intervals4/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -KNOWNBUG -intervals4.c ---intervals --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file intervals4.c line 9 function main, assertion i >= 1 && i <= 2: SUCCESS$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/intervals5/test.desc b/regression/goto-analyzer/intervals5/test.desc deleted file mode 100644 index eb64fbc13d1..00000000000 --- a/regression/goto-analyzer/intervals5/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -KNOWNBUG -intervals5.c ---intervals --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file intervals5.c line 9 function main, assertion i >= 1 || i <= 2: SUCCESS$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/intervals6/test.desc b/regression/goto-analyzer/intervals6/test.desc deleted file mode 100644 index 6e36b7948d2..00000000000 --- a/regression/goto-analyzer/intervals6/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -intervals6.c ---intervals --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file intervals6.c line 7 function main, assertion x < -10 || x > 100: FAILURE (if reachable)$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/intervals7/test.desc b/regression/goto-analyzer/intervals7/test.desc deleted file mode 100644 index 6a42b4a30ec..00000000000 --- a/regression/goto-analyzer/intervals7/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -intervals7.c ---intervals --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file intervals7.c line 7 function main, assertion x < -10 && x > 100: FAILURE (if reachable)$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/intervals8/test.desc b/regression/goto-analyzer/intervals8/test.desc deleted file mode 100644 index 7500059a717..00000000000 --- a/regression/goto-analyzer/intervals8/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -intervals8.c ---intervals --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file intervals8.c line 6 function main, assertion x < -10 && x < 100: FAILURE (if reachable)$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/intervals9/test.desc b/regression/goto-analyzer/intervals9/test.desc deleted file mode 100644 index 37c33b97288..00000000000 --- a/regression/goto-analyzer/intervals9/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -KNOWNBUG -intervals9.c ---intervals --verify -^EXIT=0$ -^SIGNAL=0$ -^\[main.assertion.1\] file intervals9.c line 9 function main, assertion i>=1 && i<=2: SUCCESS$ --- -^warning: ignoring diff --git a/regression/goto-analyzer/intervals1/intervals1.c b/regression/goto-analyzer/intervals_01/main.c similarity index 99% rename from regression/goto-analyzer/intervals1/intervals1.c rename to regression/goto-analyzer/intervals_01/main.c index cdec490fe6d..ce6294d362c 100644 --- a/regression/goto-analyzer/intervals1/intervals1.c +++ b/regression/goto-analyzer/intervals_01/main.c @@ -3,7 +3,7 @@ int main() { int i, j=20; - + if(i>=20) assert(i>=10); diff --git a/regression/goto-analyzer/intervals_01/test.desc b/regression/goto-analyzer/intervals_01/test.desc new file mode 100644 index 00000000000..e90c4aaeda6 --- /dev/null +++ b/regression/goto-analyzer/intervals_01/test.desc @@ -0,0 +1,15 @@ +CORE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 8 function main, assertion i>=10: Success$ +^\[main.assertion.2\] file main.c line 11 function main, assertion i!=30: Success$ +^\[main.assertion.3\] file main.c line 14 function main, assertion i!=15: Unknown$ +^\[main.assertion.4\] file main.c line 17 function main, assertion 0: Success$ +^\[main.assertion.5\] file main.c line 20 function main, assertion j>=10: Success$ +^\[main.assertion.6\] file main.c line 23 function main, assertion i>=j: Unknown$ +^\[main.assertion.7\] file main.c line 26 function main, assertion i>=11: Success$ +^\[main.assertion.8\] file main.c line 29 function main, assertion j<100: Success$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/intervals2/intervals2.c b/regression/goto-analyzer/intervals_02/main.c similarity index 80% rename from regression/goto-analyzer/intervals2/intervals2.c rename to regression/goto-analyzer/intervals_02/main.c index d542854bb6a..755d36df82c 100644 --- a/regression/goto-analyzer/intervals2/intervals2.c +++ b/regression/goto-analyzer/intervals_02/main.c @@ -3,9 +3,7 @@ int main(){ int x; if (x > 0 && x < 20) { - //if (x < 20) { assert(x > -10 && x < 100); - //} } return 0; } diff --git a/regression/goto-analyzer/intervals_02/test.desc b/regression/goto-analyzer/intervals_02/test.desc new file mode 100644 index 00000000000..fa4f926287f --- /dev/null +++ b/regression/goto-analyzer/intervals_02/test.desc @@ -0,0 +1,8 @@ +KNOWNBUG +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 7 function main, assertion x > -10 && x < 100: Success$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/intervals3/intervals3.c b/regression/goto-analyzer/intervals_03/main.c similarity index 100% rename from regression/goto-analyzer/intervals3/intervals3.c rename to regression/goto-analyzer/intervals_03/main.c diff --git a/regression/goto-analyzer/intervals_03/test.desc b/regression/goto-analyzer/intervals_03/test.desc new file mode 100644 index 00000000000..79042c334de --- /dev/null +++ b/regression/goto-analyzer/intervals_03/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 7 function main, assertion x > -10 || x < 100: Success$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/intervals4/intervals4.c b/regression/goto-analyzer/intervals_04/main.c similarity index 100% rename from regression/goto-analyzer/intervals4/intervals4.c rename to regression/goto-analyzer/intervals_04/main.c diff --git a/regression/goto-analyzer/intervals_04/test.desc b/regression/goto-analyzer/intervals_04/test.desc new file mode 100644 index 00000000000..5bb03255f37 --- /dev/null +++ b/regression/goto-analyzer/intervals_04/test.desc @@ -0,0 +1,8 @@ +KNOWNBUG +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 9 function main, assertion i >= 1 && i <= 2: Success$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/intervals5/intervals5.c b/regression/goto-analyzer/intervals_05/main.c similarity index 100% rename from regression/goto-analyzer/intervals5/intervals5.c rename to regression/goto-analyzer/intervals_05/main.c diff --git a/regression/goto-analyzer/intervals_05/test.desc b/regression/goto-analyzer/intervals_05/test.desc new file mode 100644 index 00000000000..5c9af29a2b1 --- /dev/null +++ b/regression/goto-analyzer/intervals_05/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 9 function main, assertion i >= 1 || i <= 2: Success$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/intervals6/intervals6.c b/regression/goto-analyzer/intervals_06/main.c similarity index 100% rename from regression/goto-analyzer/intervals6/intervals6.c rename to regression/goto-analyzer/intervals_06/main.c diff --git a/regression/goto-analyzer/intervals_06/test.desc b/regression/goto-analyzer/intervals_06/test.desc new file mode 100644 index 00000000000..2dc8d29a3b6 --- /dev/null +++ b/regression/goto-analyzer/intervals_06/test.desc @@ -0,0 +1,8 @@ +FUTURE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 7 function main, assertion x < -10 || x > 100: Failure (if reachable)$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/intervals7/intervals7.c b/regression/goto-analyzer/intervals_07/main.c similarity index 100% rename from regression/goto-analyzer/intervals7/intervals7.c rename to regression/goto-analyzer/intervals_07/main.c diff --git a/regression/goto-analyzer/intervals_07/test.desc b/regression/goto-analyzer/intervals_07/test.desc new file mode 100644 index 00000000000..aa3962f39de --- /dev/null +++ b/regression/goto-analyzer/intervals_07/test.desc @@ -0,0 +1,8 @@ +FUTURE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 7 function main, assertion x < -10 && x > 100: Failure (if reachable)$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/intervals8/intervals8.c b/regression/goto-analyzer/intervals_08/main.c similarity index 100% rename from regression/goto-analyzer/intervals8/intervals8.c rename to regression/goto-analyzer/intervals_08/main.c diff --git a/regression/goto-analyzer/intervals_08/test.desc b/regression/goto-analyzer/intervals_08/test.desc new file mode 100644 index 00000000000..7b83ecd0f21 --- /dev/null +++ b/regression/goto-analyzer/intervals_08/test.desc @@ -0,0 +1,8 @@ +FUTURE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 6 function main, assertion x < -10 && x < 100: Failure (if reachable)$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/intervals9/intervals9.c b/regression/goto-analyzer/intervals_09/main.c similarity index 100% rename from regression/goto-analyzer/intervals9/intervals9.c rename to regression/goto-analyzer/intervals_09/main.c diff --git a/regression/goto-analyzer/intervals_09/test.desc b/regression/goto-analyzer/intervals_09/test.desc new file mode 100644 index 00000000000..8145fc369ca --- /dev/null +++ b/regression/goto-analyzer/intervals_09/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 9 function main, assertion i>=1 && i<=2: Success$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/intervals10/intervals10.c b/regression/goto-analyzer/intervals_10/main.c similarity index 100% rename from regression/goto-analyzer/intervals10/intervals10.c rename to regression/goto-analyzer/intervals_10/main.c diff --git a/regression/goto-analyzer/intervals_10/test.desc b/regression/goto-analyzer/intervals_10/test.desc new file mode 100644 index 00000000000..468ce13a550 --- /dev/null +++ b/regression/goto-analyzer/intervals_10/test.desc @@ -0,0 +1,12 @@ +FUTURE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 8 function main, assertion j<=100: Success$ +^\[main.assertion.2\] file main.c line 11 function main, assertion j<101: Success$ +^\[main.assertion.3\] file main.c line 14 function main, assertion j>100: Failure (if reachable)$ +^\[main.assertion.4\] file main.c line 17 function main, assertion j<99: Unknown$ +^\[main.assertion.5\] file main.c line 20 function main, assertion j==100: Failure (if reachable)$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/intervals11/intervals11.c b/regression/goto-analyzer/intervals_11/main.c similarity index 100% rename from regression/goto-analyzer/intervals11/intervals11.c rename to regression/goto-analyzer/intervals_11/main.c diff --git a/regression/goto-analyzer/intervals_11/test.desc b/regression/goto-analyzer/intervals_11/test.desc new file mode 100644 index 00000000000..799ad36f64f --- /dev/null +++ b/regression/goto-analyzer/intervals_11/test.desc @@ -0,0 +1,9 @@ +FUTURE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 30 function main, assertion y\[i\]>=-1.0f && y\[i\]<=1.0f: Unknown$ +^\[main.assertion.2\] file main.c line 35 function main, assertion y\[i\]>=-1.0f && y\[i\]<=1.0f: Unknown$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/intervals12/intervals12.c b/regression/goto-analyzer/intervals_12/main.c similarity index 100% rename from regression/goto-analyzer/intervals12/intervals12.c rename to regression/goto-analyzer/intervals_12/main.c diff --git a/regression/goto-analyzer/intervals_12/test.desc b/regression/goto-analyzer/intervals_12/test.desc new file mode 100644 index 00000000000..ffdf46857de --- /dev/null +++ b/regression/goto-analyzer/intervals_12/test.desc @@ -0,0 +1,9 @@ +FUTURE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^[main.assertion.1] file main.c line 8 function main, assertion j < 0: Success$ +^[main.assertion.2] file main.c line 11 function main, assertion j < 0: Success$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_06/constant_propagation_06.c b/regression/goto-analyzer/intervals_13/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_06/constant_propagation_06.c rename to regression/goto-analyzer/intervals_13/main.c diff --git a/regression/goto-analyzer/intervals_13/test.desc b/regression/goto-analyzer/intervals_13/test.desc new file mode 100644 index 00000000000..e90c4aaeda6 --- /dev/null +++ b/regression/goto-analyzer/intervals_13/test.desc @@ -0,0 +1,15 @@ +CORE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 8 function main, assertion i>=10: Success$ +^\[main.assertion.2\] file main.c line 11 function main, assertion i!=30: Success$ +^\[main.assertion.3\] file main.c line 14 function main, assertion i!=15: Unknown$ +^\[main.assertion.4\] file main.c line 17 function main, assertion 0: Success$ +^\[main.assertion.5\] file main.c line 20 function main, assertion j>=10: Success$ +^\[main.assertion.6\] file main.c line 23 function main, assertion i>=j: Unknown$ +^\[main.assertion.7\] file main.c line 26 function main, assertion i>=11: Success$ +^\[main.assertion.8\] file main.c line 29 function main, assertion j<100: Success$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_08/constant_propagation_08.c b/regression/goto-analyzer/intervals_14/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_08/constant_propagation_08.c rename to regression/goto-analyzer/intervals_14/main.c diff --git a/regression/goto-analyzer/intervals_14/test.desc b/regression/goto-analyzer/intervals_14/test.desc new file mode 100644 index 00000000000..20a01bf3e12 --- /dev/null +++ b/regression/goto-analyzer/intervals_14/test.desc @@ -0,0 +1,10 @@ +FUTURE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 12 function main, assertion i<50: Unknown$ +^\[main.assertion.2\] file main.c line 13 function main, assertion i<51: Unknown$ +^\[main.assertion.3\] file main.c line 14 function main, assertion i<52: Success$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_09/constant_propagation_09.c b/regression/goto-analyzer/intervals_15/main.c similarity index 100% rename from regression/goto-analyzer/constant_propagation_09/constant_propagation_09.c rename to regression/goto-analyzer/intervals_15/main.c diff --git a/regression/goto-analyzer/intervals_15/test.desc b/regression/goto-analyzer/intervals_15/test.desc new file mode 100644 index 00000000000..7d3bae09250 --- /dev/null +++ b/regression/goto-analyzer/intervals_15/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 12 function main, assertion j<52: Unknown$ +-- +^warning: ignoring From 42e603c4d6b9e2ae42762dbff177f674d6993f8a Mon Sep 17 00:00:00 2001 From: martin Date: Wed, 24 May 2017 17:48:40 +0100 Subject: [PATCH 016/129] Addressing goto analyzer review comments by Daniel Poetzl. --- .../goto_analyzer_parse_options.cpp | 4 +- src/goto-analyzer/static_analyzer.cpp | 40 +++--- src/goto-analyzer/static_show_domain.cpp | 17 ++- src/goto-analyzer/static_show_domain.h | 1 - src/goto-analyzer/static_simplifier.cpp | 123 ++++++++---------- src/goto-analyzer/static_simplifier.h | 1 - 6 files changed, 89 insertions(+), 97 deletions(-) diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index 1619e568bbd..081c8b723a5 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -589,7 +589,7 @@ void goto_analyzer_parse_optionst::help() { std::cout << "\n" - "* * GOTO-ANALYZER " CBMC_VERSION " - Copyright (C) 2016 "; + "* * GOTO-ANALYZER " CBMC_VERSION " - Copyright (C) 2017 "; std::cout << "(" << (sizeof(void *)*8) << "-bit version)"; @@ -613,7 +613,7 @@ void goto_analyzer_parse_optionst::help() "\n" "Abstract interpreter options:\n" " --flow-sensitive use flow-sensitive abstract interpreter\n" - " --concurrent use concurrent abstract interpreter\n" + " --concurrent use concurrency-aware abstract interpreter\n" "\n" "Domain options:\n" " --constants constant domain\n" diff --git a/src/goto-analyzer/static_analyzer.cpp b/src/goto-analyzer/static_analyzer.cpp index 960bedd3f12..5456b0e5d82 100644 --- a/src/goto-analyzer/static_analyzer.cpp +++ b/src/goto-analyzer/static_analyzer.cpp @@ -10,6 +10,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include #include @@ -17,7 +18,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "static_analyzer.h" -template +template class static_analyzert:public messaget { public: @@ -91,7 +92,8 @@ void static_analyzert::plain_text_report() if(!i_it->is_assert()) continue; - exprt simplified=domain[i_it].domain_simplify(i_it->guard, ns); + exprt e(i_it->guard); + domain[i_it].ai_simplify(e, ns); result() << '[' << i_it->source_location.get_property_id() << ']' << ' '; @@ -103,17 +105,20 @@ void static_analyzert::plain_text_report() result() << ": "; - if(simplified.is_true()) + if(e.is_true()) { - result() << "SUCCESS"; pass++; + result() << "Success"; + pass++; } - else if(simplified.is_false()) + else if(e.is_false()) { - result() << "FAILURE (if reachable)"; fail++; + result() << "Failure (if reachable)"; + fail++; } else { - result() << "UNKNOWN"; unknown++; + result() << "Unknown"; + unknown++; } result() << eom; @@ -122,7 +127,7 @@ void static_analyzert::plain_text_report() status() << '\n'; } - status() << "SUMMARY: " << pass << " pass, " << fail << " fail if reachable, " + status() << "Summary: " << pass << " pass, " << fail << " fail if reachable, " << unknown << " unknown\n"; } @@ -146,21 +151,19 @@ void static_analyzert::json_report() if(!i_it->is_assert()) continue; - exprt simplified=domain[i_it].domain_simplify(i_it->guard, ns); + exprt e(i_it->guard); + domain[i_it].ai_simplify(e, ns); json_objectt &j=json_result.push_back().make_object(); - if(simplified.is_true()) + if(e.is_true()) j["status"]=json_stringt("SUCCESS"); - else if(simplified.is_false()) + else if(e.is_false()) j["status"]=json_stringt("FAILURE (if reachable)"); else j["status"]=json_stringt("UNKNOWN"); - j["file"]=json_stringt(id2string(i_it->source_location.get_file())); - j["line"]=json_numbert(id2string(i_it->source_location.get_line())); - j["description"]=json_stringt(id2string( - i_it->source_location.get_comment())); + j["sourceLocation"]=json(i_it->source_location); } } status() << "Writing JSON report" << eom; @@ -187,13 +190,14 @@ void static_analyzert::xml_report() if(!i_it->is_assert()) continue; - exprt simplified=domain[i_it].domain_simplify(i_it->guard, ns); + exprt e(i_it->guard); + domain[i_it].ai_simplify(e, ns); xmlt &x=xml_result.new_element("result"); - if(simplified.is_true()) + if(e.is_true()) x.set_attribute("status", "SUCCESS"); - else if(simplified.is_false()) + else if(e.is_false()) x.set_attribute("status", "FAILURE (if reachable)"); else x.set_attribute("status", "UNKNOWN"); diff --git a/src/goto-analyzer/static_show_domain.cpp b/src/goto-analyzer/static_show_domain.cpp index 412c45e2bc2..036290e0d1d 100644 --- a/src/goto-analyzer/static_show_domain.cpp +++ b/src/goto-analyzer/static_show_domain.cpp @@ -6,7 +6,14 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk \*******************************************************************/ +//#define DEBUG + +#ifdef DEBUG +#include +#endif + #include +#include #include #include @@ -37,13 +44,17 @@ bool static_show_domain( message_handlert &message_handler, std::ostream &out) { - ai_baset *domain = NULL; + ai_baset *domain=nullptr; + namespacet ns(goto_model.symbol_table); if(options.get_bool_option("flow-sensitive")) { if(options.get_bool_option("constants")) - domain=new ait(); + { + //domain=new ait(); + domain=new constant_propagator_ait(goto_model.goto_functions); + } else if(options.get_bool_option("intervals")) domain=new ait(); else if(options.get_bool_option("dependence-graph")) @@ -64,7 +75,7 @@ bool static_show_domain( #endif } - if(domain==NULL) + if(domain==nullptr) { messaget m(message_handler); m.status() << "Task / Interpreter / Domain combination not supported" diff --git a/src/goto-analyzer/static_show_domain.h b/src/goto-analyzer/static_show_domain.h index 3f0e7da3680..bedb1e7faed 100644 --- a/src/goto-analyzer/static_show_domain.h +++ b/src/goto-analyzer/static_show_domain.h @@ -12,7 +12,6 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk #include #include -#include #include #include diff --git a/src/goto-analyzer/static_simplifier.cpp b/src/goto-analyzer/static_simplifier.cpp index ce5bd8c511d..f1ac76189f7 100644 --- a/src/goto-analyzer/static_simplifier.cpp +++ b/src/goto-analyzer/static_simplifier.cpp @@ -52,7 +52,7 @@ class static_simplifiert:public messaget analyzerT domain; void simplify_program(void); - unsigned simplify_guard(goto_programt::instructionst::iterator &i_it); + bool simplify_guard(goto_programt::instructionst::iterator &i_it); }; /*******************************************************************\ @@ -96,30 +96,6 @@ bool static_simplifiert::operator()(void) return write_goto_binary(out, ns.get_symbol_table(), goto_functions); } - -/*******************************************************************\ - -Function: static_simplifiert::simplify_guard - - Inputs: An iterator pointing to an instruction. - - Outputs: 1 if simplified, 0 if not. - - Purpose: Simplifies the instruction's guard using the information in - the abstract domain. - -\*******************************************************************/ - -template -unsigned static_simplifiert::simplify_guard( - goto_programt::instructionst::iterator &i_it) -{ - exprt simplified=domain[i_it].domain_simplify(i_it->guard, ns); - unsigned return_value=(simplified==i_it->guard)?0:1; - i_it->guard=simplified; - return return_value; -} - /*******************************************************************\ Function: static_simplifiert::simplify_program @@ -138,6 +114,13 @@ void static_simplifiert::simplify_program() { struct counterst { + counterst() : + asserts(0), + assumes(0), + gotos(0), + assigns(0), + function_calls(0) {} + unsigned asserts; unsigned assumes; unsigned gotos; @@ -145,8 +128,8 @@ void static_simplifiert::simplify_program() unsigned function_calls; }; - counterst simplified={0, 0, 0, 0, 0}; - counterst unmodified={0, 0, 0, 0, 0}; + counterst simplified; + counterst unmodified; Forall_goto_functions(f_it, goto_functions) { @@ -154,70 +137,66 @@ void static_simplifiert::simplify_program() { if(i_it->is_assert()) { - unsigned result=simplify_guard(i_it); - simplified.asserts+=result; - unmodified.asserts+=(1-result); + bool unchanged=domain[i_it].ai_simplify(i_it->guard, ns); + + if(unchanged) + unmodified.asserts++; + else + simplified.asserts++; } else if(i_it->is_assume()) { - unsigned result=simplify_guard(i_it); - simplified.assumes+=result; - unmodified.assumes+=(1-result); + bool unchanged=domain[i_it].ai_simplify(i_it->guard, ns); + + if(unchanged) + unmodified.assumes++; + else + simplified.assumes++; } else if(i_it->is_goto()) { - unsigned result=simplify_guard(i_it); - simplified.gotos+=result; - unmodified.gotos+=(1-result); + bool unchanged=domain[i_it].ai_simplify(i_it->guard, ns); + + if(unchanged) + unmodified.gotos++; + else + simplified.gotos++; } else if(i_it->is_assign()) { - code_assignt assign(to_code_assign(i_it->code)); + code_assignt &assign=to_code_assign(i_it->code); - /* - Simplification needs to be aware of which side of the - expression it is handling as: - i=j - should simplify to i=1, not to 0=1. - */ + // Simplification needs to be aware of which side of the + // expression it is handling as: + // i=j + // should simplify to i=1, not to 0=1. - exprt simp_lhs=domain[i_it].domain_simplify(assign.lhs(), ns, true); - exprt simp_rhs=domain[i_it].domain_simplify(assign.rhs(), ns, false); + bool unchanged_lhs= + domain[i_it].ai_simplify(assign.lhs(), ns, true); - unsigned result=(simp_lhs==assign.lhs() && - simp_rhs==assign.rhs())?0:1; + bool unchanged_rhs= + domain[i_it].ai_simplify(assign.rhs(), ns, false); - simplified.assigns+=result; - unmodified.assigns+=(1-result); - - assign.lhs()=simp_lhs; - assign.rhs()=simp_rhs; - i_it->code=assign; + if(unchanged_lhs && unchanged_rhs) + unmodified.assigns++; + else + simplified.assigns++; } else if(i_it->is_function_call()) { - unsigned result=0; - code_function_callt fcall(to_code_function_call(i_it->code)); + code_function_callt &fcall=to_code_function_call(i_it->code); - exprt new_function=domain[i_it].domain_simplify(fcall.function(), ns); - result|=(new_function==fcall.function()) ? 0 : 1; - fcall.function()=new_function; + bool unchanged=domain[i_it].ai_simplify(fcall.function(), ns); exprt::operandst &args=fcall.arguments(); - for(exprt::operandst::iterator o_it=args.begin(); - o_it!=args.end(); - ++o_it) - { - exprt new_arg=domain[i_it].domain_simplify(*o_it, ns); - result|=(new_arg==*o_it) ? 0 : 1; - *o_it=new_arg; - } - - i_it->code=fcall; + for(auto &o : args) + unchanged&=domain[i_it].ai_simplify(o, ns); - simplified.function_calls+=result; - unmodified.function_calls+=(1-result); + if(unchanged) + unmodified.function_calls++; + else + simplified.function_calls++; } } } @@ -225,14 +204,14 @@ void static_simplifiert::simplify_program() // Make sure the references are correct. goto_functions.update(); - status() << "SIMPLIFIED: " + status() << "Simplified: " << " assert: " << simplified.asserts << ", assume: " << simplified.assumes << ", goto: " << simplified.gotos << ", assigns: " << simplified.assigns << ", function calls: " << simplified.function_calls << "\n" - << "UNMODIFIED: " + << "Unmodified: " << " assert: " << unmodified.asserts << ", assume: " << unmodified.assumes << ", goto: " << unmodified.gotos diff --git a/src/goto-analyzer/static_simplifier.h b/src/goto-analyzer/static_simplifier.h index c9d4e156b7a..61bb77dad1d 100644 --- a/src/goto-analyzer/static_simplifier.h +++ b/src/goto-analyzer/static_simplifier.h @@ -12,7 +12,6 @@ Author: Lucas Cordeiro, lucas.cordeiro@cs.ox.ac.uk #include #include -#include #include #include From 74170fdbbe2c8e9424c616e54b41175478dbf6ba Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Fri, 10 Feb 2017 12:34:54 +0000 Subject: [PATCH 017/129] option to ignore unresolved functions in the constant propagator --- src/analyses/constant_propagator.cpp | 26 +++++++++++++------ src/analyses/constant_propagator.h | 8 ++++-- .../goto_analyzer_parse_options.cpp | 3 +++ .../goto_analyzer_parse_options.h | 3 ++- src/goto-analyzer/static_show_domain.cpp | 6 +++-- 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/analyses/constant_propagator.cpp b/src/analyses/constant_propagator.cpp index e1e22baaee8..491d562c9a2 100644 --- a/src/analyses/constant_propagator.cpp +++ b/src/analyses/constant_propagator.cpp @@ -65,6 +65,10 @@ void constant_propagator_domaint::transform( const constant_propagator_ait *cp= dynamic_cast(&ai); bool have_dirty=(cp!=nullptr); + bool ignore_unresolved_calls=false; + + if(have_dirty) + ignore_unresolved_calls=cp->ignore_unresolved_calls; // assert(!values.is_bottom); if(values.is_bottom) @@ -138,10 +142,13 @@ void constant_propagator_domaint::transform( } else { - if(have_dirty) - values.set_dirty_to_top(cp->dirty, ns); - else - values.set_to_top(); + if(!ignore_unresolved_calls) + { + if(have_dirty) + values.set_dirty_to_top(cp->dirty, ns); + else + values.set_to_top(); + } } } else @@ -175,10 +182,13 @@ void constant_propagator_domaint::transform( assert(to==next); - if(have_dirty) - values.set_dirty_to_top(cp->dirty, ns); - else - values.set_to_top(); + if(!ignore_unresolved_calls) + { + if(have_dirty) + values.set_dirty_to_top(cp->dirty, ns); + else + values.set_to_top(); + } } } else if(from->is_end_function()) diff --git a/src/analyses/constant_propagator.h b/src/analyses/constant_propagator.h index 1b98e6272fe..d65b9194ca7 100644 --- a/src/analyses/constant_propagator.h +++ b/src/analyses/constant_propagator.h @@ -153,8 +153,11 @@ class constant_propagator_domaint:public ai_domain_baset class constant_propagator_ait:public ait { public: - explicit constant_propagator_ait(const goto_functionst &goto_functions): - dirty(goto_functions) + explicit constant_propagator_ait( + const goto_functionst &goto_functions, + const bool ignore_unresolved_calls=false) : + dirty(goto_functions), + ignore_unresolved_calls(ignore_unresolved_calls) { } @@ -175,6 +178,7 @@ class constant_propagator_ait:public ait } dirtyt dirty; + bool ignore_unresolved_calls; protected: friend class constant_propagator_domaint; diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index 081c8b723a5..2b35417c62a 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -234,6 +234,9 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) status() << "Domain defaults to --constants" << eom; options.set_option("constants", true); } + + if(cmdline.isset("ignore-unresolved-calls")) + options.set_option("ignore-unresolved-calls", true); } /// invoke main modules diff --git a/src/goto-analyzer/goto_analyzer_parse_options.h b/src/goto-analyzer/goto_analyzer_parse_options.h index 6ec661093c5..31f13fba023 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.h +++ b/src/goto-analyzer/goto_analyzer_parse_options.h @@ -50,7 +50,8 @@ class optionst; "(dependence-graph)" \ "(show)(verify)(simplify):" \ "(flow-sensitive)(concurrent)" \ - "(no-simplify-slicing)" + "(no-simplify-slicing)" \ + "(ignore-unresolved-calls)" class goto_analyzer_parse_optionst: public parse_options_baset, diff --git a/src/goto-analyzer/static_show_domain.cpp b/src/goto-analyzer/static_show_domain.cpp index 036290e0d1d..bf576f5a55c 100644 --- a/src/goto-analyzer/static_show_domain.cpp +++ b/src/goto-analyzer/static_show_domain.cpp @@ -52,8 +52,10 @@ bool static_show_domain( { if(options.get_bool_option("constants")) { - //domain=new ait(); - domain=new constant_propagator_ait(goto_model.goto_functions); + domain= + new constant_propagator_ait( + goto_model.goto_functions, + options.get_bool_option("ignore-unresolved-calls")); } else if(options.get_bool_option("intervals")) domain=new ait(); From ec808bd8b6f479b79a89b99fc6bd49e6923e3819 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 23 May 2017 20:40:03 +0100 Subject: [PATCH 018/129] Test that requires is_bottom() and is_top(). --- .../goto-analyzer/constant_propagation_16/main.c | 13 +++++++++++++ .../goto-analyzer/constant_propagation_16/test.desc | 7 +++++++ 2 files changed, 20 insertions(+) create mode 100644 regression/goto-analyzer/constant_propagation_16/main.c create mode 100644 regression/goto-analyzer/constant_propagation_16/test.desc diff --git a/regression/goto-analyzer/constant_propagation_16/main.c b/regression/goto-analyzer/constant_propagation_16/main.c new file mode 100644 index 00000000000..22fbac6a427 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_16/main.c @@ -0,0 +1,13 @@ + +void func() +{ + while(1) {} +} + +int main() +{ + func(); + + return 0; +} + diff --git a/regression/goto-analyzer/constant_propagation_16/test.desc b/regression/goto-analyzer/constant_propagation_16/test.desc new file mode 100644 index 00000000000..ef4ab9321a2 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_16/test.desc @@ -0,0 +1,7 @@ +CORE +main.c +--show --constants +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring From f1c62f2366a925a2b63336e7ec6935e8656244b8 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 23 May 2017 20:45:39 +0100 Subject: [PATCH 019/129] Improve status output. --- src/goto-analyzer/static_analyzer.cpp | 8 ++++++-- src/goto-analyzer/static_show_domain.cpp | 9 ++++++--- src/goto-analyzer/static_simplifier.cpp | 6 ++++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/goto-analyzer/static_analyzer.cpp b/src/goto-analyzer/static_analyzer.cpp index 5456b0e5d82..e50192233ee 100644 --- a/src/goto-analyzer/static_analyzer.cpp +++ b/src/goto-analyzer/static_analyzer.cpp @@ -57,9 +57,11 @@ class static_analyzert:public messaget template bool static_analyzert::operator()() { - status() << "Performing analysis" << eom; + status() << "Computing abstract states" << eom; domain(goto_functions, ns); + status() << "Checking assertions" << eom; + if(options.get_bool_option("json")) json_report(); else if(options.get_bool_option("xml")) @@ -225,6 +227,9 @@ bool static_analyzer( message_handlert &message_handler, std::ostream &out) { + messaget m(message_handler); + m.status() << "Selecting abstract domain" << messaget::eom; + if(options.get_bool_option("flow-sensitive")) { if(options.get_bool_option("constants")) @@ -258,7 +263,6 @@ bool static_analyzer( #endif } - messaget m(message_handler); m.status() << "Task / Interpreter / Domain combination not supported" << messaget::eom; diff --git a/src/goto-analyzer/static_show_domain.cpp b/src/goto-analyzer/static_show_domain.cpp index bf576f5a55c..b39e1a244af 100644 --- a/src/goto-analyzer/static_show_domain.cpp +++ b/src/goto-analyzer/static_show_domain.cpp @@ -6,7 +6,7 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk \*******************************************************************/ -//#define DEBUG +// #define DEBUG #ifdef DEBUG #include @@ -47,6 +47,9 @@ bool static_show_domain( ai_baset *domain=nullptr; namespacet ns(goto_model.symbol_table); + messaget m(message_handler); + + m.status() << "Selecting abstract domain" << messaget::eom; if(options.get_bool_option("flow-sensitive")) { @@ -79,15 +82,15 @@ bool static_show_domain( if(domain==nullptr) { - messaget m(message_handler); m.status() << "Task / Interpreter / Domain combination not supported" << messaget::eom; return true; } - // status() << "Performing analysis" << eom; + m.status() << "Computing abstract states" << messaget::eom; (*domain)(goto_model); + m.status() << "Outputting abstract states" << messaget::eom; if(options.get_bool_option("json")) out << domain->output_json(goto_model); diff --git a/src/goto-analyzer/static_simplifier.cpp b/src/goto-analyzer/static_simplifier.cpp index f1ac76189f7..b28e7501c0a 100644 --- a/src/goto-analyzer/static_simplifier.cpp +++ b/src/goto-analyzer/static_simplifier.cpp @@ -71,7 +71,7 @@ Function: static_simplifiert::operator() template bool static_simplifiert::operator()(void) { - status() << "Performing analysis" << eom; + status() << "Computing abstract states" << eom; domain(goto_functions, ns); status() << "Simplifying program" << eom; @@ -241,6 +241,9 @@ bool static_simplifier( message_handlert &message_handler, std::ostream &out) { + messaget m(message_handler); + m.status() << "Selecting abstract domain" << messaget::eom; + if(options.get_bool_option("flow-sensitive")) { if(options.get_bool_option("constants")) @@ -274,7 +277,6 @@ bool static_simplifier( #endif } - messaget m(message_handler); m.status() << "Task / Interpreter / Domain combination not supported" << messaget::eom; From 7ca4e945f36dd87a08e80b2cd633a72720813b69 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Wed, 22 Feb 2017 20:37:52 +0000 Subject: [PATCH 020/129] enable failed tests printer for goto-analyzer regression tests --- regression/goto-analyzer/intervals_09/test.desc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regression/goto-analyzer/intervals_09/test.desc b/regression/goto-analyzer/intervals_09/test.desc index 8145fc369ca..83776b8ae34 100644 --- a/regression/goto-analyzer/intervals_09/test.desc +++ b/regression/goto-analyzer/intervals_09/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --intervals --verify ^EXIT=0$ From ca7d8abe1fc88fbed3f762cc227902d372cb9c9b Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Fri, 24 Feb 2017 16:59:03 +0000 Subject: [PATCH 021/129] enable assertions in is_threadedt --- .../goto-analyzer/constant_propagation_01/main.c | 1 - .../constant_propagation_01/test.desc | 2 +- .../goto-analyzer/constant_propagation_02/main.c | 1 - .../constant_propagation_02/test.desc | 2 +- .../goto-analyzer/constant_propagation_03/main.c | 1 - .../goto-analyzer/constant_propagation_04/main.c | 1 - .../goto-analyzer/constant_propagation_05/main.c | 1 - .../goto-analyzer/constant_propagation_06/main.c | 1 - .../constant_propagation_06/test.desc | 2 +- .../goto-analyzer/constant_propagation_07/main.c | 2 +- .../goto-analyzer/constant_propagation_08/main.c | 2 +- .../goto-analyzer/constant_propagation_09/main.c | 2 +- .../goto-analyzer/constant_propagation_10/main.c | 2 +- .../goto-analyzer/constant_propagation_11/main.c | 2 +- .../goto-analyzer/constant_propagation_12/main.c | 2 +- .../goto-analyzer/constant_propagation_13/main.c | 2 +- .../goto-analyzer/constant_propagation_14/main.c | 2 +- .../goto-analyzer/constant_propagation_15/main.c | 2 +- .../goto-analyzer/constant_propagation_17/main.c | 14 ++++++++++++++ .../constant_propagation_17/test.desc | 8 ++++++++ regression/goto-analyzer/intervals_01/main.c | 1 - regression/goto-analyzer/intervals_01/test.desc | 16 ++++++++-------- regression/goto-analyzer/intervals_02/main.c | 1 - regression/goto-analyzer/intervals_03/main.c | 1 - regression/goto-analyzer/intervals_04/main.c | 1 - regression/goto-analyzer/intervals_05/main.c | 1 - regression/goto-analyzer/intervals_06/main.c | 1 - regression/goto-analyzer/intervals_07/main.c | 1 - regression/goto-analyzer/intervals_08/main.c | 1 - regression/goto-analyzer/intervals_09/main.c | 1 - regression/goto-analyzer/intervals_10/main.c | 1 - regression/goto-analyzer/intervals_11/main.c | 2 +- regression/goto-analyzer/intervals_12/main.c | 1 - regression/goto-analyzer/intervals_13/main.c | 1 - regression/goto-analyzer/intervals_13/test.desc | 16 ++++++++-------- regression/goto-analyzer/intervals_14/main.c | 1 - regression/goto-analyzer/intervals_15/main.c | 1 - regression/goto-analyzer/intervals_15/test.desc | 2 +- regression/goto-analyzer/intervals_16/main.c | 13 +++++++++++++ regression/goto-analyzer/intervals_16/test.desc | 8 ++++++++ src/analyses/is_threaded.cpp | 10 ++-------- 41 files changed, 75 insertions(+), 58 deletions(-) create mode 100644 regression/goto-analyzer/constant_propagation_17/main.c create mode 100644 regression/goto-analyzer/constant_propagation_17/test.desc create mode 100644 regression/goto-analyzer/intervals_16/main.c create mode 100644 regression/goto-analyzer/intervals_16/test.desc diff --git a/regression/goto-analyzer/constant_propagation_01/main.c b/regression/goto-analyzer/constant_propagation_01/main.c index 801a21535a9..6689d8d4562 100644 --- a/regression/goto-analyzer/constant_propagation_01/main.c +++ b/regression/goto-analyzer/constant_propagation_01/main.c @@ -1,4 +1,3 @@ -#include int main() { diff --git a/regression/goto-analyzer/constant_propagation_01/test.desc b/regression/goto-analyzer/constant_propagation_01/test.desc index f5aa9da5608..a4a79f28ab1 100644 --- a/regression/goto-analyzer/constant_propagation_01/test.desc +++ b/regression/goto-analyzer/constant_propagation_01/test.desc @@ -3,7 +3,7 @@ main.c --constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 2, assigns: 5, function calls: 0$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 5, function calls: 0$ ^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 12, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_02/main.c b/regression/goto-analyzer/constant_propagation_02/main.c index ff139437bd8..db0c8dc3f3e 100644 --- a/regression/goto-analyzer/constant_propagation_02/main.c +++ b/regression/goto-analyzer/constant_propagation_02/main.c @@ -1,4 +1,3 @@ -#include int main() { diff --git a/regression/goto-analyzer/constant_propagation_02/test.desc b/regression/goto-analyzer/constant_propagation_02/test.desc index a7074d70c31..6a28820a4b0 100644 --- a/regression/goto-analyzer/constant_propagation_02/test.desc +++ b/regression/goto-analyzer/constant_propagation_02/test.desc @@ -3,7 +3,7 @@ main.c --constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 6, function calls: 0$ ^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_03/main.c b/regression/goto-analyzer/constant_propagation_03/main.c index f08f6020d82..09a5434dead 100644 --- a/regression/goto-analyzer/constant_propagation_03/main.c +++ b/regression/goto-analyzer/constant_propagation_03/main.c @@ -1,4 +1,3 @@ -#include int main() { diff --git a/regression/goto-analyzer/constant_propagation_04/main.c b/regression/goto-analyzer/constant_propagation_04/main.c index ca003ccd2b8..2c6c3f39db1 100644 --- a/regression/goto-analyzer/constant_propagation_04/main.c +++ b/regression/goto-analyzer/constant_propagation_04/main.c @@ -1,4 +1,3 @@ -#include int main() { diff --git a/regression/goto-analyzer/constant_propagation_05/main.c b/regression/goto-analyzer/constant_propagation_05/main.c index 037fbbe0632..b740fc135c0 100644 --- a/regression/goto-analyzer/constant_propagation_05/main.c +++ b/regression/goto-analyzer/constant_propagation_05/main.c @@ -1,4 +1,3 @@ -#include int main() { diff --git a/regression/goto-analyzer/constant_propagation_06/main.c b/regression/goto-analyzer/constant_propagation_06/main.c index 40b04edfdd0..6290aa89e6b 100644 --- a/regression/goto-analyzer/constant_propagation_06/main.c +++ b/regression/goto-analyzer/constant_propagation_06/main.c @@ -1,4 +1,3 @@ -#include int main() { diff --git a/regression/goto-analyzer/constant_propagation_06/test.desc b/regression/goto-analyzer/constant_propagation_06/test.desc index da9d7778bbf..77a7349569f 100644 --- a/regression/goto-analyzer/constant_propagation_06/test.desc +++ b/regression/goto-analyzer/constant_propagation_06/test.desc @@ -3,6 +3,6 @@ main.c --constants --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line 12 function main, assertion i<51: Unknown$ +^\[main.assertion.1\] file main.c line 11 function main, assertion i\s*<\s*51: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_07/main.c b/regression/goto-analyzer/constant_propagation_07/main.c index f0dea39a424..1fb6fee8e15 100644 --- a/regression/goto-analyzer/constant_propagation_07/main.c +++ b/regression/goto-analyzer/constant_propagation_07/main.c @@ -1,4 +1,4 @@ -#include + int main() { signed int i; diff --git a/regression/goto-analyzer/constant_propagation_08/main.c b/regression/goto-analyzer/constant_propagation_08/main.c index 3022a4f0f19..295e23c636d 100644 --- a/regression/goto-analyzer/constant_propagation_08/main.c +++ b/regression/goto-analyzer/constant_propagation_08/main.c @@ -1,4 +1,4 @@ -#include + int main() { int a[2]; diff --git a/regression/goto-analyzer/constant_propagation_09/main.c b/regression/goto-analyzer/constant_propagation_09/main.c index 55ea9ac7fc2..9bd38159f67 100644 --- a/regression/goto-analyzer/constant_propagation_09/main.c +++ b/regression/goto-analyzer/constant_propagation_09/main.c @@ -1,4 +1,4 @@ -#include + int main() { int a[2]={0,0}; diff --git a/regression/goto-analyzer/constant_propagation_10/main.c b/regression/goto-analyzer/constant_propagation_10/main.c index ac5933e9177..217faa4c9a7 100644 --- a/regression/goto-analyzer/constant_propagation_10/main.c +++ b/regression/goto-analyzer/constant_propagation_10/main.c @@ -1,4 +1,4 @@ -#include + int main() { int a[2]={0,0}; diff --git a/regression/goto-analyzer/constant_propagation_11/main.c b/regression/goto-analyzer/constant_propagation_11/main.c index 124d1e30a20..cefa0c479ab 100644 --- a/regression/goto-analyzer/constant_propagation_11/main.c +++ b/regression/goto-analyzer/constant_propagation_11/main.c @@ -1,4 +1,4 @@ -#include + int main() { int a[2]={0,0}; diff --git a/regression/goto-analyzer/constant_propagation_12/main.c b/regression/goto-analyzer/constant_propagation_12/main.c index 9a7e7692d62..a8379b64712 100644 --- a/regression/goto-analyzer/constant_propagation_12/main.c +++ b/regression/goto-analyzer/constant_propagation_12/main.c @@ -1,4 +1,4 @@ -#include + int main() { int i=0, y; diff --git a/regression/goto-analyzer/constant_propagation_13/main.c b/regression/goto-analyzer/constant_propagation_13/main.c index 102cfd7f812..a4307c4d431 100644 --- a/regression/goto-analyzer/constant_propagation_13/main.c +++ b/regression/goto-analyzer/constant_propagation_13/main.c @@ -1,4 +1,4 @@ -#include + int main() { int i=0, y; diff --git a/regression/goto-analyzer/constant_propagation_14/main.c b/regression/goto-analyzer/constant_propagation_14/main.c index 8b426fe84b5..7a659b87c60 100644 --- a/regression/goto-analyzer/constant_propagation_14/main.c +++ b/regression/goto-analyzer/constant_propagation_14/main.c @@ -1,4 +1,4 @@ -#include + int main() { int a[2]={0,0}; diff --git a/regression/goto-analyzer/constant_propagation_15/main.c b/regression/goto-analyzer/constant_propagation_15/main.c index 6639f9b5c81..e3dd672831d 100644 --- a/regression/goto-analyzer/constant_propagation_15/main.c +++ b/regression/goto-analyzer/constant_propagation_15/main.c @@ -1,4 +1,4 @@ -#include + int main() { int a[2]={0,0}; diff --git a/regression/goto-analyzer/constant_propagation_17/main.c b/regression/goto-analyzer/constant_propagation_17/main.c new file mode 100644 index 00000000000..40b04edfdd0 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_17/main.c @@ -0,0 +1,14 @@ +#include + +int main() +{ + int i=0, j=2; + + while (i<50) + { + i++; + j++; + } + assert(i<51); +} + diff --git a/regression/goto-analyzer/constant_propagation_17/test.desc b/regression/goto-analyzer/constant_propagation_17/test.desc new file mode 100644 index 00000000000..76dc0fca897 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_17/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--constants --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 12 function main, assertion i\s*<\s*51: (Unknown|Failure \(if reachable\))$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/intervals_01/main.c b/regression/goto-analyzer/intervals_01/main.c index ce6294d362c..aeb37b99e07 100644 --- a/regression/goto-analyzer/intervals_01/main.c +++ b/regression/goto-analyzer/intervals_01/main.c @@ -1,4 +1,3 @@ -#include int main() { diff --git a/regression/goto-analyzer/intervals_01/test.desc b/regression/goto-analyzer/intervals_01/test.desc index e90c4aaeda6..af3180985b5 100644 --- a/regression/goto-analyzer/intervals_01/test.desc +++ b/regression/goto-analyzer/intervals_01/test.desc @@ -3,13 +3,13 @@ main.c --intervals --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line 8 function main, assertion i>=10: Success$ -^\[main.assertion.2\] file main.c line 11 function main, assertion i!=30: Success$ -^\[main.assertion.3\] file main.c line 14 function main, assertion i!=15: Unknown$ -^\[main.assertion.4\] file main.c line 17 function main, assertion 0: Success$ -^\[main.assertion.5\] file main.c line 20 function main, assertion j>=10: Success$ -^\[main.assertion.6\] file main.c line 23 function main, assertion i>=j: Unknown$ -^\[main.assertion.7\] file main.c line 26 function main, assertion i>=11: Success$ -^\[main.assertion.8\] file main.c line 29 function main, assertion j<100: Success$ +^\[main.assertion.1\] file main.c line 7 function main, assertion i\s*>=\s*10: Success$ +^\[main.assertion.2\] file main.c line 10 function main, assertion i\s*!=\s*30: Success$ +^\[main.assertion.3\] file main.c line 13 function main, assertion i\s*!=\s*15: Unknown$ +^\[main.assertion.4\] file main.c line 16 function main, assertion 0: Success$ +^\[main.assertion.5\] file main.c line 19 function main, assertion j\s*>=\s*10: Success$ +^\[main.assertion.6\] file main.c line 22 function main, assertion i\s*>=\s*j: Unknown$ +^\[main.assertion.7\] file main.c line 25 function main, assertion i\s*>=\s*11: Success$ +^\[main.assertion.8]\ file main.c line 28 function main, assertion j\s*<\s*100: Success$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/intervals_02/main.c b/regression/goto-analyzer/intervals_02/main.c index 755d36df82c..00659353325 100644 --- a/regression/goto-analyzer/intervals_02/main.c +++ b/regression/goto-analyzer/intervals_02/main.c @@ -1,4 +1,3 @@ -#include int main(){ int x; diff --git a/regression/goto-analyzer/intervals_03/main.c b/regression/goto-analyzer/intervals_03/main.c index bbaa3ce4e1e..de8c1eead32 100644 --- a/regression/goto-analyzer/intervals_03/main.c +++ b/regression/goto-analyzer/intervals_03/main.c @@ -1,4 +1,3 @@ -#include int main(){ int x; diff --git a/regression/goto-analyzer/intervals_04/main.c b/regression/goto-analyzer/intervals_04/main.c index 790a5f1379f..1ca11e32143 100644 --- a/regression/goto-analyzer/intervals_04/main.c +++ b/regression/goto-analyzer/intervals_04/main.c @@ -1,4 +1,3 @@ -//#include int main() { diff --git a/regression/goto-analyzer/intervals_05/main.c b/regression/goto-analyzer/intervals_05/main.c index ed19ba71590..2cd79130dc9 100644 --- a/regression/goto-analyzer/intervals_05/main.c +++ b/regression/goto-analyzer/intervals_05/main.c @@ -1,4 +1,3 @@ -//#include int main() { diff --git a/regression/goto-analyzer/intervals_06/main.c b/regression/goto-analyzer/intervals_06/main.c index e93240e7573..0e8a1f37c13 100644 --- a/regression/goto-analyzer/intervals_06/main.c +++ b/regression/goto-analyzer/intervals_06/main.c @@ -1,4 +1,3 @@ -#include int main(){ int x; diff --git a/regression/goto-analyzer/intervals_07/main.c b/regression/goto-analyzer/intervals_07/main.c index c893c413ad5..75da9413b97 100644 --- a/regression/goto-analyzer/intervals_07/main.c +++ b/regression/goto-analyzer/intervals_07/main.c @@ -1,4 +1,3 @@ -#include int main(){ int x; diff --git a/regression/goto-analyzer/intervals_08/main.c b/regression/goto-analyzer/intervals_08/main.c index 4128ac07ce5..3bcb7fe69c7 100644 --- a/regression/goto-analyzer/intervals_08/main.c +++ b/regression/goto-analyzer/intervals_08/main.c @@ -1,4 +1,3 @@ -#include int main(){ int x; diff --git a/regression/goto-analyzer/intervals_09/main.c b/regression/goto-analyzer/intervals_09/main.c index 27739c7aa28..73b8e73dc85 100644 --- a/regression/goto-analyzer/intervals_09/main.c +++ b/regression/goto-analyzer/intervals_09/main.c @@ -1,4 +1,3 @@ -#include int main() { diff --git a/regression/goto-analyzer/intervals_10/main.c b/regression/goto-analyzer/intervals_10/main.c index b27cc6f2001..b245b3f5b7c 100644 --- a/regression/goto-analyzer/intervals_10/main.c +++ b/regression/goto-analyzer/intervals_10/main.c @@ -1,4 +1,3 @@ -#include int main() { diff --git a/regression/goto-analyzer/intervals_11/main.c b/regression/goto-analyzer/intervals_11/main.c index 2f061cd554d..a6496ef764d 100644 --- a/regression/goto-analyzer/intervals_11/main.c +++ b/regression/goto-analyzer/intervals_11/main.c @@ -1,4 +1,4 @@ -#include + const int xLen = 10; const int Alen = 2; const int Blen = 1; diff --git a/regression/goto-analyzer/intervals_12/main.c b/regression/goto-analyzer/intervals_12/main.c index 15d865adf80..506e118f898 100644 --- a/regression/goto-analyzer/intervals_12/main.c +++ b/regression/goto-analyzer/intervals_12/main.c @@ -1,4 +1,3 @@ -#include int main (void) { int i; diff --git a/regression/goto-analyzer/intervals_13/main.c b/regression/goto-analyzer/intervals_13/main.c index d1d29427250..b631969e8f6 100644 --- a/regression/goto-analyzer/intervals_13/main.c +++ b/regression/goto-analyzer/intervals_13/main.c @@ -1,4 +1,3 @@ -#include int main() { diff --git a/regression/goto-analyzer/intervals_13/test.desc b/regression/goto-analyzer/intervals_13/test.desc index e90c4aaeda6..8d9720faf63 100644 --- a/regression/goto-analyzer/intervals_13/test.desc +++ b/regression/goto-analyzer/intervals_13/test.desc @@ -3,13 +3,13 @@ main.c --intervals --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line 8 function main, assertion i>=10: Success$ -^\[main.assertion.2\] file main.c line 11 function main, assertion i!=30: Success$ -^\[main.assertion.3\] file main.c line 14 function main, assertion i!=15: Unknown$ -^\[main.assertion.4\] file main.c line 17 function main, assertion 0: Success$ -^\[main.assertion.5\] file main.c line 20 function main, assertion j>=10: Success$ -^\[main.assertion.6\] file main.c line 23 function main, assertion i>=j: Unknown$ -^\[main.assertion.7\] file main.c line 26 function main, assertion i>=11: Success$ -^\[main.assertion.8\] file main.c line 29 function main, assertion j<100: Success$ +^\[main.assertion.1\] file main.c line 7 function main, assertion i\s*>=\s*10: Success$ +^\[main.assertion.2\] file main.c line 10 function main, assertion i\s*!=\s*30: Success$ +^\[main.assertion.3\] file main.c line 13 function main, assertion i\s*!=\s*15: Unknown$ +^\[main.assertion.4\] file main.c line 16 function main, assertion 0: Success$ +^\[main.assertion.5\] file main.c line 19 function main, assertion j\s*>=\s*10: Success$ +^\[main.assertion.6\] file main.c line 22 function main, assertion i\s*>=\s*j: Unknown$ +^\[main.assertion.7\] file main.c line 25 function main, assertion i\s*>=\s*11: Success$ +^\[main.assertion.8\] file main.c line 28 function main, assertion j\s*<\s*100: Success$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/intervals_14/main.c b/regression/goto-analyzer/intervals_14/main.c index 3909e3889e4..7e4d53d5e06 100644 --- a/regression/goto-analyzer/intervals_14/main.c +++ b/regression/goto-analyzer/intervals_14/main.c @@ -1,4 +1,3 @@ -#include int main() { diff --git a/regression/goto-analyzer/intervals_15/main.c b/regression/goto-analyzer/intervals_15/main.c index 002e9063228..52ef248b772 100644 --- a/regression/goto-analyzer/intervals_15/main.c +++ b/regression/goto-analyzer/intervals_15/main.c @@ -1,4 +1,3 @@ -#include int main() { diff --git a/regression/goto-analyzer/intervals_15/test.desc b/regression/goto-analyzer/intervals_15/test.desc index 7d3bae09250..e61667afcd4 100644 --- a/regression/goto-analyzer/intervals_15/test.desc +++ b/regression/goto-analyzer/intervals_15/test.desc @@ -3,6 +3,6 @@ main.c --intervals --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line 12 function main, assertion j<52: Unknown$ +^\[main.assertion.1\] file main.c line 11 function main, assertion j\s*<\s*52: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/intervals_16/main.c b/regression/goto-analyzer/intervals_16/main.c new file mode 100644 index 00000000000..52ef248b772 --- /dev/null +++ b/regression/goto-analyzer/intervals_16/main.c @@ -0,0 +1,13 @@ + +int main() +{ + int i=0, j=2; + + while (i<=50) + { + i++; + j++; + } + assert(j<52); +} + diff --git a/regression/goto-analyzer/intervals_16/test.desc b/regression/goto-analyzer/intervals_16/test.desc new file mode 100644 index 00000000000..c23e2bcf4f5 --- /dev/null +++ b/regression/goto-analyzer/intervals_16/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line 11 function main, assertion j\s*<\s*52: (Unknown|Failure \(if reachable\))$ +-- +^warning: ignoring diff --git a/src/analyses/is_threaded.cpp b/src/analyses/is_threaded.cpp index d6276cbdb27..88a36e9961a 100644 --- a/src/analyses/is_threaded.cpp +++ b/src/analyses/is_threaded.cpp @@ -32,10 +32,7 @@ class is_threaded_domaint:public ai_domain_baset locationt from, locationt to) { - // assert(src.reachable); - - if(!src.reachable) - return false; + assert(src.reachable); bool old_reachable=reachable; bool old_is_threaded=is_threaded; @@ -53,10 +50,7 @@ class is_threaded_domaint:public ai_domain_baset ai_baset &ai, const namespacet &ns) final override { - // assert(reachable); - - if(!reachable) - return; + assert(reachable); if(from->is_start_thread()) is_threaded=true; From 3565cc6c835088852eec7942c0b358113754ad34 Mon Sep 17 00:00:00 2001 From: martin Date: Thu, 15 Jun 2017 16:41:07 +0100 Subject: [PATCH 022/129] Update the use of ai_simplify for the introduction of ai_simplify_lhs. --- src/goto-analyzer/static_simplifier.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/goto-analyzer/static_simplifier.cpp b/src/goto-analyzer/static_simplifier.cpp index b28e7501c0a..140496bd636 100644 --- a/src/goto-analyzer/static_simplifier.cpp +++ b/src/goto-analyzer/static_simplifier.cpp @@ -172,10 +172,10 @@ void static_simplifiert::simplify_program() // should simplify to i=1, not to 0=1. bool unchanged_lhs= - domain[i_it].ai_simplify(assign.lhs(), ns, true); + domain[i_it].ai_simplify_lhs(assign.lhs(), ns); bool unchanged_rhs= - domain[i_it].ai_simplify(assign.rhs(), ns, false); + domain[i_it].ai_simplify(assign.rhs(), ns); if(unchanged_lhs && unchanged_rhs) unmodified.assigns++; From 5abec1e5a4bea917e2e37fad3db2c1c736e0e08e Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 14 Feb 2017 18:08:37 +0000 Subject: [PATCH 023/129] Check in of basic variable sensitivity framework. This includes skeleton code written by @martin-cs. Added hook for running the variable sensitivity Involved removing messaget inheritance since we require a zero parameter constructor for ai_baset Terminate correctly Made the domain correclty find the fixed point. The merge operation returns whether the merge actually changed any values by implementing a operator== for each of the abstract objects. Further, when merging a map, if a key is absent from one map then we remove it from the other unless the map is bottom. Adding handlers for the special types They are just stubs at the moment, returning top as we need the abstract objects that represent them. Updated interface for ai_domain_baset --- src/analyses/Makefile | 3 + .../abstract_enviroment.cpp | 456 ++++++++++++++++++ .../abstract_enviroment.h | 63 +++ .../variable-sensitivity/abstract_object.cpp | 245 ++++++++++ .../variable-sensitivity/abstract_object.h | 97 ++++ .../variable_sensitivity_domain.cpp | 238 +++++++++ .../variable_sensitivity_domain.h | 56 +++ .../goto_analyzer_parse_options.cpp | 10 +- .../goto_analyzer_parse_options.h | 1 + src/goto-analyzer/static_analyzer.cpp | 5 + src/goto-analyzer/static_show_domain.cpp | 3 + src/goto-analyzer/static_simplifier.cpp | 5 + 12 files changed, 1181 insertions(+), 1 deletion(-) create mode 100644 src/analyses/variable-sensitivity/abstract_enviroment.cpp create mode 100644 src/analyses/variable-sensitivity/abstract_enviroment.h create mode 100644 src/analyses/variable-sensitivity/abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/abstract_object.h create mode 100644 src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp create mode 100644 src/analyses/variable-sensitivity/variable_sensitivity_domain.h diff --git a/src/analyses/Makefile b/src/analyses/Makefile index 9be0609687f..e27444b7222 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -24,6 +24,9 @@ SRC = ai.cpp \ reaching_definitions.cpp \ static_analysis.cpp \ uninitialized_domain.cpp \ + variable-sensitivity/abstract_object.cpp \ + variable-sensitivity/abstract_enviroment.cpp \ + variable-sensitivity/variable_sensitivity_domain.cpp \ # Empty last line INCLUDES= -I .. diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp new file mode 100644 index 00000000000..742e9f8a749 --- /dev/null +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -0,0 +1,456 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#include "abstract_enviroment.h" +#include +#include +#include +#include + + + +/*******************************************************************\ + +Function: abstract_environmentt::eval + + Inputs: + expr - the expression to evaluate + + Outputs: The abstract_object representing the value of the expression + + Purpose: Evaluate the value of an expression + +\*******************************************************************/ + +abstract_object_pointert abstract_environmentt::eval( + const exprt &expr) const +{ + typedef std::function eval_handlert; + static std::map handlers= + { + { + ID_symbol, [&](const exprt &expr) + { + const symbol_exprt &symbol(to_symbol_expr(expr)); + const auto &symbol_entry=map.find(symbol); + if(symbol_entry==map.cend()) + { + return abstract_object_factory(expr.type(), true); + } + else + { + return symbol_entry->second; + } + } + }, + { + ID_member, [&](const exprt &expr) + { +#if 0 + member_exprt member_expr(to_member_expr(expr)); +#endif + // TODO(tkiley): eval the compound to (hopefully) get an + // abstract_struct_objectt then use that to get an AO for a specific + // component. + // For now, just return top + return abstract_object_pointert( + new abstract_objectt(expr.type(), true, false)); + } + }, + { + ID_address_of, [&](const exprt &expr) + { +#if 0 + address_of_exprt address_expr(to_address_of_expr(expr)); +#endif + // TODO(tkiley): This needs special handling + // For now just return top + return abstract_object_pointert( + new abstract_objectt(expr.type(), true, false)); + } + }, + { + ID_dereference, [&](const exprt &expr) + { + #if 0 + dereference_exprt dereference(to_dereference_expr(expr)); + #endif + // TODO(tkiley): eval the pointer to (hopefully) get an + // abstract_pointer_objectt then use that to get an AO for a specific + // value. + // For now, just return top + return abstract_object_pointert( + new abstract_objectt(expr.type(), true, false)); + } + }, + { + ID_index, [&](const exprt &expr) + { +#if 0 + index_exprt index_expr(to_index_expr(expr)); +#endif + // TODO(tkiley): eval the array to (hopefully) get an + // abstract_array_objectt then use that to get an AO for a specific + // index. + // For now, just return top + return abstract_object_pointert( + new abstract_objectt(expr.type(), true, false)); + } + } + }; + + const auto &handler=handlers.find(expr.id()); + if(handler==handlers.cend()) + { + return abstract_object_factory(expr.type(), true); + } + else + { + return handler->second(expr); + } +} + +/*******************************************************************\ + +Function: abstract_environmentt::assign + + Inputs: + expr - the expression to assign to + value - the value to assign to the expression + + Outputs: ? + + Purpose: Assign a value to an expression + +\*******************************************************************/ + +bool abstract_environmentt::assign( + const exprt &expr, const abstract_object_pointert value) +{ + exprt s = expr; + std::stack stactions; // I'm not a continuation, honest guv' + + while (s.id() != ID_symbol) + { + if (s.id() == ID_index || s.id() == ID_member) + { + stactions.push(s); + s = s.op0(); + } + else if (s.id() == ID_dereference) + { + // LOL, nope! + } + else + { + // Attempting to assign to something unreasonable + // Your goto-program is broken + throw "die_horribly"; + } + } + + const symbol_exprt &symbol_expr(to_symbol_expr(s)); + + if (!stactions.empty()) + { + throw "not yet implemented"; + } + if (value->is_top()) + { + map.erase(symbol_expr); + } + else + { + map[symbol_expr]=value; + } + + return true; +} + +/*******************************************************************\ + +Function: abstract_environmentt::assume + + Inputs: + expr - the expression inside the assume + + Outputs: ? + + Purpose: ? + +\*******************************************************************/ + +bool abstract_environmentt::assume(const exprt &expr) +{ + abstract_object_pointert res = eval(expr); + std::string not_implemented_string=__func__; + not_implemented_string.append(" not implemented"); + throw not_implemented_string; + // Need abstract_booleant +#if 0 + abstract_booleant *b = dynamic_cast(res); + + assert(b != NULL); + + if (b->to_constant().is_false()) + { + make_bottom(); + return true; + } + else + return false; +#endif +} + + +/*******************************************************************\ + +Function: abstract_environmentt::abstract_object_factory + + Inputs: + type - the type of the object whose state should be tracked + top - does the type of the object start as top + + Outputs: The abstract object that has been created + + Purpose: Look at the configuration for the sensitivity and create an + appropriate abstract_object + +\*******************************************************************/ + +abstract_object_pointert abstract_environmentt::abstract_object_factory( + const typet type, bool top) const +{ + // TODO (tkiley): Here we should look at some config file + return abstract_object_pointert(new abstract_objectt(type, top, false)); +} + +/*******************************************************************\ + +Function: abstract_environmentt::abstract_object_factory + + Inputs: + type - the type of the object whose state should be tracked + expr - the starting value of the symbol + + Outputs: The abstract object that has been created + + Purpose: Look at the configuration for the sensitivity and create an + appropriate abstract_object, assigning an appropriate value + +\*******************************************************************/ + +abstract_objectt *abstract_environmentt::abstract_object_factory( + const typet t, const constant_exprt e) const +{ + assert(t==e.type()); + return new abstract_objectt(e); +} + +/*******************************************************************\ + +Function: abstract_environmentt::merge + + Inputs: + env - the other environment + + Outputs: ? + + Purpose: ? + +\*******************************************************************/ + +bool abstract_environmentt::merge(const abstract_environmentt &env) +{ + // Use the sharing_map's "iterative over all differences" functionality + // This should give a significant performance boost + // We can strip down to just the things that are in both + + // for each entry in the incoming environment we need to either add it + // if it is new, or merge with the existing key if it is not present + + bool modified=false; + for(const auto &entry:env.map) + { + if(map.find(entry.first)==map.end()) + { + // We only add new stuff if we are bottom + if(is_bottom) + { + map[entry.first] = entry.second; + modified=true; + } + } + else + { + bool object_modified=false; + abstract_object_pointert new_object=map[entry.first]->merge( + entry.second, object_modified); + + if(object_modified) + { + modified=true; + } + map[entry.first]=new_object; + + } + + if(map[entry.first]->is_top()) + { + map.erase(entry.first); + is_bottom=false; + modified=true; + } + } + + std::vector to_remove; + for(const auto &entry : map) + { + if(env.map.find(entry.first)==env.map.end()) + { + to_remove.push_back(entry.first); + } + } + for(const map_keyt &key_to_remove : to_remove) + { + map.erase(key_to_remove); + } + return modified; +} + +/*******************************************************************\ + +Function: abstract_environmentt::havoc + + Inputs: + havoc_string - debug string to track down havoc causing. + + Outputs: + + Purpose: Set the domain to top + +\*******************************************************************/ + +void abstract_environmentt::havoc(const std::string &havoc_string) +{ + // TODO(tkiley): error reporting + make_top(); +} + +/*******************************************************************\ + +Function: abstract_environmentt::make_top + + Inputs: + + Outputs: + + Purpose: Set the domain to top + +\*******************************************************************/ + +void abstract_environmentt::make_top() +{ + // since we assume anything is not in the map is top this is sufficient + // TODO: need a flag for bottom + map.clear(); + is_bottom=false; +} + +/*******************************************************************\ + +Function: abstract_environmentt::make_bottom + + Inputs: + + Outputs: + + Purpose: Set the domain to top + +\*******************************************************************/ + +void abstract_environmentt::make_bottom() +{ + map.clear(); + is_bottom=true; +} + +/*******************************************************************\ + +Function: abstract_environmentt::get_is_bottom + + Inputs: + + Outputs: + + Purpose: Gets whether the domain is bottom + +\*******************************************************************/ + +bool abstract_environmentt::get_is_bottom() const +{ + return map.empty() && is_bottom; +} + +/*******************************************************************\ + +Function: abstract_environmentt::get_is_top + + Inputs: + + Outputs: + + Purpose: Gets whether the domain is top + +\*******************************************************************/ + +bool abstract_environmentt::get_is_top() const +{ + return map.empty() && !is_bottom; +} + +/*******************************************************************\ +Function: abstract_environmentt::output + + Inputs: + out - the stream to write to + ai - ? + ns - ? + + Outputs: + + Purpose: Print out all the values in the abstract object map + +\*******************************************************************/ + +void abstract_environmentt::output( + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const +{ + out << "{\n"; + + for(const auto &entry : map) + { + out << entry.first.get_identifier() + << " (" << ") -> "; + entry.second->output(out, ai, ns); + out << "\n"; + } + out << "}\n"; +} + +abstract_object_pointert abstract_environmentt::eval_logical( + const exprt &e) const +{ + throw "not implemented"; +} + +abstract_object_pointert abstract_environmentt::eval_rest(const exprt &e) const +{ + return abstract_object_factory(e.type()); +} diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h new file mode 100644 index 00000000000..dedd120710c --- /dev/null +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -0,0 +1,63 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_ENVIROMENT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_ENVIROMENT_H + +#include +#include + +#include +#include +#include + +class abstract_environmentt +{ +public: + // These three are really the heart of the method + virtual abstract_object_pointert eval(const exprt &expr) const; + virtual bool assign(const exprt &expr, const abstract_object_pointert value); + virtual bool assume(const exprt &expr); + + virtual abstract_object_pointert abstract_object_factory( + const typet type, bool top = true) const; + // For converting constants in the program + // Maybe these two should be compacted to one call... + virtual abstract_objectt *abstract_object_factory( + const typet t, const constant_exprt e) const; + + + virtual bool merge(const abstract_environmentt &env); + + // This should be used as a default case / everything else has failed + // The string is so that I can easily find and diagnose cases where this occurs + virtual void havoc(const std::string &havoc_string); + + void make_top(); + void make_bottom(); + + bool get_is_bottom() const; + bool get_is_top() const; + + void output( + std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; + +protected: + bool is_bottom; + + // We may need to break out more of these cases into these + virtual abstract_object_pointert eval_logical(const exprt &e) const; + + // Hook for domain specific handling of operators + virtual abstract_object_pointert eval_rest(const exprt &e) const; + + typedef symbol_exprt map_keyt; + std::map map; + +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_ENVIROMENT_H diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp new file mode 100644 index 00000000000..1a2321f6739 --- /dev/null +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -0,0 +1,245 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ + +#include "abstract_object.h" +#include +#include +#include + +/*******************************************************************\ + +Function: abstract_objectt::abstract_objectt + + Inputs: + type - the type the abstract_object is representing + + Outputs: + + Purpose: + +\*******************************************************************/ + +abstract_objectt::abstract_objectt(const typet &type): +type(type), top(true), bottom(false) +{} + +/*******************************************************************\ + +Function: abstract_objectt::abstract_objectt + + Inputs: + type - the type the abstract_object is representing + top - is the abstract_object starting as top + bottom - is the abstract_object starting as bottom + + Outputs: + + Purpose: Start the abstract object at either top or bottom or neither + Asserts if both top and bottom are true + +\*******************************************************************/ + +abstract_objectt::abstract_objectt(const typet &type, bool top, bool bottom): + type(type), top(top), bottom(bottom) +{ + assert(!(top && bottom)); +} + +/*******************************************************************\ + +Function: abstract_objectt::abstract_objectt + + Inputs: + old - the abstract object to copy from + + Outputs: + + Purpose: + +\*******************************************************************/ + +abstract_objectt::abstract_objectt(const abstract_objectt &old): + type(old.type), top(old.top), bottom(old.bottom) +{} + +/*******************************************************************\ + +Function: abstract_objectt::abstract_objectt + + Inputs: + expr - the expression to use as the starting pointer for an abstract object + + Outputs: + + Purpose: + +\*******************************************************************/ + +abstract_objectt::abstract_objectt(const constant_exprt &expr): +type(expr.type()), top(true), bottom(false) +{} + +const typet &abstract_objectt::get_type() const +{ + return type; +} + +/*******************************************************************\ + +Function: abstract_objectt::merge_state + + Inputs: + op1 - the first abstract object + op2 - the second abstract object + + Outputs: + + Purpose: Set this abstract object to be the result of merging two + other abstract objects. This is the worst case - we can + only set to top or bottom. + +\*******************************************************************/ + +void abstract_objectt::merge_state( + const abstract_object_pointert op1, const abstract_object_pointert op2) +{ + top=op1->top||op2->top; + bottom=op1->bottom && op2->bottom; + assert(!(top && bottom)); +} + +/*******************************************************************\ + +Function: abstract_objectt::merge + + Inputs: + op - the abstract object to merge with + + Outputs: + + Purpose: Set this abstract object to be the result of merging this + abstract object and the provided one. See merge_state. + +\*******************************************************************/ + +abstract_object_pointert abstract_objectt::merge( + const abstract_object_pointert op, bool &out_any_modifications) +{ + assert(this->type==op->type); + abstract_object_pointert m=abstract_object_pointert(new abstract_objectt(*this)); + m->merge_state(abstract_object_pointert(new abstract_objectt(*this)), op); + out_any_modifications=!(*m==*this); + return m; +} + +/*******************************************************************\ + +Function: abstract_objectt::is_top + + Inputs: + + Outputs: Returns true if the abstract object is representing the top (i.e. we + don't know anything about the value). + + Purpose: Find out if the abstract object is top + +\*******************************************************************/ + +bool abstract_objectt::is_top() const +{ + return top; +} + +/*******************************************************************\ + +Function: abstract_objectt::is_bottom + + Inputs: + + Outputs: Returns true if the abstract object is representing the bottom. + + Purpose: Find out if the abstract object is bottom + +\*******************************************************************/ + +bool abstract_objectt::is_bottom() const +{ + return bottom; +} + +/*******************************************************************\ + +Function: abstract_objectt::to_constant + + Inputs: + + Outputs: Returns an exprt representing the value if the value is known and + constant. Otherwise returns the nil expression + + Purpose: If abstract element represents a single value, then that value, + otherwise nil. E.G. if it is an interval then this will be x if it is + [x,x] This is the (sort of) dual to the constant_exprt constructor + that allows an object to be built from a value. + +\*******************************************************************/ + +exprt abstract_objectt::to_constant() const +{ + return nil_exprt(); +} + +/*******************************************************************\ + +Function: abstract_objectt::output + + Inputs: + out - the stream to write to + ai - ? + ns - ? + + Outputs: + + Purpose: Print the value of the abstract object + +\*******************************************************************/ + +void abstract_objectt::output( + std::ostream &out, const ai_baset &ai, const namespacet &ns) +{ + if(top) + { + out << "TOP"; + } + else if(bottom) + { + out << "BOTTOM"; + } + else + { + out << "Unknown"; + } +} + +/*******************************************************************\ + +Function: abstract_objectt::operator== + + Inputs: + other - the abstract_object to compare + + Outputs: Returns true if the two abstract objects are equivalent + + Purpose: Check to AOs are representing the same value according to + their sensitivity. + +\*******************************************************************/ + +bool abstract_objectt::operator==(const abstract_objectt &other) const +{ + return top==other.top && bottom==other.bottom; +} diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h new file mode 100644 index 00000000000..f01b6fe7ca6 --- /dev/null +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -0,0 +1,97 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H + +class typet; +class constant_exprt; + +#include +#include + + +#define CLONE \ + virtual abstract_objectt* clone() const \ + { \ + typedef std::remove_const::type \ + >::type current_typet; \ + return new current_typet(*this); \ + } \ + +#define MERGE(parent_typet) \ + virtual abstract_object_pointert merge( \ + const abstract_object_pointert op, \ + bool &out_any_modifications) \ + {\ + assert(this->type==op->type); \ + typedef std::remove_const::type \ + >::type current_typet; \ + \ + /*Check the supplied parent type is indeed a parent*/ \ + static_assert(std::is_base_of::value, \ + "parent_typet in MERGE must be parent class of the current type"); \ + \ + typedef sharing_ptrt current_type_ptrt; \ + /*Cast the supplied type to the current type to facilitate double dispatch*/ \ + current_type_ptrt n=std::dynamic_pointer_cast(op); \ + current_type_ptrt m=current_type_ptrt(new current_typet(*this)); \ + if (n!= NULL) \ + { \ + m->merge_state(current_type_ptrt(new current_typet(*this)), n); \ + out_any_modifications=!(*this==*m); \ + return m; \ + } \ + else \ + { \ + return parent_typet::merge( \ + abstract_object_pointert(op), out_any_modifications); \ + } \ + } \ + +template +using sharing_ptrt=std::shared_ptr; + +typedef sharing_ptrt abstract_object_pointert; + +class abstract_objectt +{ +public: + abstract_objectt(const typet &type); + abstract_objectt(const typet &type, bool top, bool bottom); + abstract_objectt(const abstract_objectt &old); + abstract_objectt(const constant_exprt &expr); + + const typet &get_type() const; + virtual bool is_top() const; + virtual bool is_bottom() const; + + // Sets the state of this object + void merge_state( + const abstract_object_pointert op1, const abstract_object_pointert op2); + + // This is both the interface and the base case of the recursion + // It uses merge state to + virtual abstract_object_pointert merge( + const abstract_object_pointert op, bool &out_any_modifications); + + virtual exprt to_constant() const; + + virtual void output( + std::ostream &out, const class ai_baset &ai, const class namespacet &ns); + + CLONE + + virtual bool operator==(const abstract_objectt &other) const; + + //protected + typet type; + bool top; + bool bottom; +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp new file mode 100644 index 00000000000..e14245b48db --- /dev/null +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -0,0 +1,238 @@ +/*******************************************************************\ + +Module: Abstract Interpretation + +Author: Martin Brain + +Date: April 2016 + +\*******************************************************************/ + + +#include + +#include "variable_sensitivity_domain.h" + + +/*******************************************************************\ + +Function: variable_sensitivity_domaint::transform + + Inputs: The instruction before (from) and after (to) the abstract domain, + the abstract interpreter (ai) and the namespace (ns). + + Outputs: None + + Purpose: Compute the abstract transformer for a single instruction + +\*******************************************************************/ + +void variable_sensitivity_domaint::transform( + locationt from, + locationt to, + ai_baset &ai, + const namespacet &ns) +{ + const goto_programt::instructiont &instruction=*from; + switch(instruction.type) + { + case DECL: + // Creates a new variable, which should be top + // but we don't store top so ... no action required + break; + + case DEAD: + { + // Assign to top is the same as removing + abstract_object_pointert top_object= + abstract_state.abstract_object_factory( + to_code_dead(instruction.code).symbol().type(), true); + abstract_state.assign(to_code_dead(instruction.code).symbol(), top_object); + } + break; + + case ASSIGN: + { + const code_assignt &inst = to_code_assign(instruction.code); + + // TODO : check return values + abstract_object_pointert r = abstract_state.eval(inst.rhs()); + abstract_state.assign(inst.lhs(), r); + } + break; + + case GOTO: + { + // TODO(tkiley): add support for flow sensitivity +#if 0 + if (flow_sensitivity == FLOW_SENSITIVE) + { + locationt next=from; + next++; + if(next==to) + assume(not_exprt(instruction.guard)); + else + assume(instruction.guard); + } +#endif + } + break; + + case ASSUME: + abstract_state.assume(instruction.guard); + break; + + case FUNCTION_CALL: + // FIXME : Ignore as not yet interprocedural + break; + + case END_FUNCTION: + // FIXME : Ignore as not yet interprocedural + break; + + /***************************************************************/ + + case ASSERT: + // Conditions on the program, do not alter the data or information + // flow and thus can be ignored. + break; + + case SKIP: + case LOCATION: + // Can ignore + break; + + case RETURN: + throw "return instructions should be removed first"; + + case START_THREAD: + case END_THREAD: + case ATOMIC_BEGIN: + case ATOMIC_END: + throw "threading not supported"; + + case THROW: + case CATCH: + throw "exceptions not handled"; + + case OTHER: +// throw "other"; + break; + + default: + throw "unrecognised instruction type"; + } +} + +/*******************************************************************\ + +Function: variable_sensitivity_domaint::output + + Inputs: The output stream (out), the abstract interpreter (ai) and + the namespace. + + Outputs: None + + Purpose: Basic text output of the abstract domain + +\*******************************************************************/ +void variable_sensitivity_domaint::output( + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const +{ + abstract_state.output(out, ai, ns); +} + +/*******************************************************************\ + +Function: variable_sensitivity_domaint::make_bottom + + Inputs: None + + Outputs: None + + Purpose: Sets the domain to bottom (no relations). + +\*******************************************************************/ +void variable_sensitivity_domaint::make_bottom() +{ + abstract_state.make_bottom(); + + return; +} + +/*******************************************************************\ + +Function: variable_sensitivity_domaint::make_top + + Inputs: None + + Outputs: None + + Purpose: Sets the domain to top (all relations). + +\*******************************************************************/ +void variable_sensitivity_domaint::make_top() +{ + abstract_state.make_top(); +} + + +/*******************************************************************\ + +Function: variable_sensitivity_domaint::make_entry + + Inputs: None + + Outputs: None + + Purpose: Set up a sane entry state. + +\*******************************************************************/ +void variable_sensitivity_domaint::make_entry() +{ + abstract_state.make_bottom(); + is_set_to_bottom=false; +} + +/*******************************************************************\ + +Function: variable_sensitivity_domaint::merge + + Inputs: The other domain (b) and it's preceding location (from) and + current location (to). + + Outputs: True if something has changed. + + Purpose: Computes the join between "this" and "b". + +\*******************************************************************/ + +bool variable_sensitivity_domaint::merge( + const variable_sensitivity_domaint &b, + locationt from, + locationt to) +{ + // Use the abstract_environment merge + bool any_changes=abstract_state.merge(b.abstract_state); + if(abstract_state.get_is_bottom() && !is_set_to_bottom) + { + is_set_to_bottom=true; + return true; + } + else + { + return any_changes; + } +} + +bool variable_sensitivity_domaint::is_bottom() const +{ + return is_set_to_bottom && abstract_state.get_is_bottom(); +} + +bool variable_sensitivity_domaint::is_top() const +{ + return abstract_state.get_is_top(); +} diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h new file mode 100644 index 00000000000..db21dd24512 --- /dev/null +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -0,0 +1,56 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#ifndef CPROVER_GOTO_ANALYZER_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H +#define CPROVER_GOTO_ANALYZER_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H + +#include +#include + +#include +#include + +class variable_sensitivity_domaint : public ai_domain_baset +{ +public: + virtual void transform( + locationt from, + locationt to, + ai_baset &ai, + const namespacet &ns) override; + + // no states + virtual void make_bottom() override; + + // all states -- the analysis doesn't use this, + // and domains may refuse to implement it. + virtual void make_top() override; + + // a reasonable entry-point state + virtual void make_entry() override; + + virtual void output( + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const override; + + virtual bool merge( + const variable_sensitivity_domaint &b, + locationt from, + locationt to); + + bool is_bottom() const override; + bool is_top() const override; + +private: + abstract_environmentt abstract_state; + bool is_set_to_bottom; + + +}; + +#endif // CPROVER_GOTO_ANALYZER_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H // NOLINT(*) diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index 2b35417c62a..6dc43b54701 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -213,6 +213,7 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) options.set_option("constants", false); options.set_option("intervals", false); options.set_option("non-null", false); + options.set_option("variable", false); options.set_option("dependence-graph", false); if(cmdline.isset("intervals") || @@ -223,13 +224,16 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) options.set_option("non-null", true); else if(cmdline.isset("constants")) options.set_option("constants", true); + else if(cmdline.isset("variable")) + options.set_option("variable", true); else if(cmdline.isset("dependence-graph")) options.set_option("dependence-graph", true); if(!(options.get_bool_option("constants") || options.get_bool_option("intervals") || options.get_bool_option("non-null") || - options.get_bool_option("dependence-graph"))) + options.get_bool_option("dependence-graph") || + options.get_bool_option("variable"))) { status() << "Domain defaults to --constants" << eom; options.set_option("constants", true); @@ -623,6 +627,10 @@ void goto_analyzer_parse_optionst::help() " --intervals interval domain\n" " --non-null non-null domain\n" " --dependence-graph data and control dependencies between instructions\n" // NOLINT(*) + " --variable variable sensitivity domain\n" + " --arrays enable array sensitivity in the variable sensitivity domain\n" // NOLINT(*) + " --pointers enable pointer sensitivity in the variable sensitivity domain\n" // NOLINT(*) + " --structs enable struct sensitivity in the variable sensitivity domain\n" // NOLINT(*) "\n" "Output options:\n" " --text file_name output results in plain text to given file\n" diff --git a/src/goto-analyzer/goto_analyzer_parse_options.h b/src/goto-analyzer/goto_analyzer_parse_options.h index 31f13fba023..af2ca44af78 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.h +++ b/src/goto-analyzer/goto_analyzer_parse_options.h @@ -46,6 +46,7 @@ class optionst; "(reachable-functions)" \ "(intervals)(show-intervals)" \ "(non-null)(show-non-null)" \ + "(variable)" \ "(constants)" \ "(dependence-graph)" \ "(show)(verify)(simplify):" \ diff --git a/src/goto-analyzer/static_analyzer.cpp b/src/goto-analyzer/static_analyzer.cpp index e50192233ee..be47933be27 100644 --- a/src/goto-analyzer/static_analyzer.cpp +++ b/src/goto-analyzer/static_analyzer.cpp @@ -15,6 +15,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include "static_analyzer.h" @@ -240,6 +241,10 @@ bool static_analyzer( return static_analyzert> (goto_model, options, message_handler, out)(); + else if(options.get_bool_option("variable")) + return static_analyzert>( + goto_model, options, message_handler, out)(); + // else if(options.get_bool_option("non-null")) // return static_analyzert > // (goto_model, options, message_handler, out)(); diff --git a/src/goto-analyzer/static_show_domain.cpp b/src/goto-analyzer/static_show_domain.cpp index b39e1a244af..9046bb56f07 100644 --- a/src/goto-analyzer/static_show_domain.cpp +++ b/src/goto-analyzer/static_show_domain.cpp @@ -22,6 +22,7 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk #include #include #include +#include #include "static_show_domain.h" @@ -64,6 +65,8 @@ bool static_show_domain( domain=new ait(); else if(options.get_bool_option("dependence-graph")) domain=new dependence_grapht(ns); + else if(options.get_bool_option("variable")) + domain=new ait(); } else if(options.get_bool_option("concurrent")) { diff --git a/src/goto-analyzer/static_simplifier.cpp b/src/goto-analyzer/static_simplifier.cpp index 140496bd636..8a89a0fdab7 100644 --- a/src/goto-analyzer/static_simplifier.cpp +++ b/src/goto-analyzer/static_simplifier.cpp @@ -16,6 +16,7 @@ Author: Lucas Cordeiro, lucas.cordeiro@cs.ox.ac.uk #include #include +#include #include #include @@ -254,6 +255,10 @@ bool static_simplifier( return static_simplifiert> (goto_model, options, message_handler, out)(); + else if(options.get_bool_option("variable")) + return static_simplifiert>( + goto_model, options, message_handler, out)(); + // else if(options.get_bool_option("non-null")) // return static_simplifiert > // (goto_model, options, message_handler, out)(); From 29b5a82e9ccb780019265e8c859fcc4470a8c01d Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Feb 2017 11:54:19 +0000 Subject: [PATCH 024/129] Added constant_abstract_value implementation Adding ==operator to the constant abstract value --- src/analyses/Makefile | 2 + .../abstract_enviroment.cpp | 43 ++++++++-- .../abstract_enviroment.h | 4 +- .../variable-sensitivity/abstract_object.cpp | 2 +- .../variable-sensitivity/abstract_value.cpp | 72 ++++++++++++++++ .../variable-sensitivity/abstract_value.h | 26 ++++++ .../constant_abstract_value.cpp | 82 +++++++++++++++++++ .../constant_abstract_value.h | 47 +++++++++++ 8 files changed, 269 insertions(+), 9 deletions(-) create mode 100644 src/analyses/variable-sensitivity/abstract_value.cpp create mode 100644 src/analyses/variable-sensitivity/abstract_value.h create mode 100644 src/analyses/variable-sensitivity/constant_abstract_value.cpp create mode 100644 src/analyses/variable-sensitivity/constant_abstract_value.h diff --git a/src/analyses/Makefile b/src/analyses/Makefile index e27444b7222..d5d5085b4be 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -26,6 +26,8 @@ SRC = ai.cpp \ uninitialized_domain.cpp \ variable-sensitivity/abstract_object.cpp \ variable-sensitivity/abstract_enviroment.cpp \ + variable-sensitivity/abstract_value.cpp \ + variable-sensitivity/constant_abstract_value.cpp \ variable-sensitivity/variable_sensitivity_domain.cpp \ # Empty last line diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 742e9f8a749..8831e4d7028 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -47,6 +48,13 @@ abstract_object_pointert abstract_environmentt::eval( } } }, + { + ID_constant, [&](const exprt &expr) + { + return abstract_object_factory( + expr.type(), to_constant_expr(expr)); + } + }, { ID_member, [&](const exprt &expr) { @@ -102,7 +110,14 @@ abstract_object_pointert abstract_environmentt::eval( } } }; - + #if 0 + [&](const exprt &expr) + { + return abstract_object_factory( + expr.type(), to_constant_expr(expr)); + } + } +#endif const auto &handler=handlers.find(expr.id()); if(handler==handlers.cend()) { @@ -226,7 +241,15 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( const typet type, bool top) const { // TODO (tkiley): Here we should look at some config file - return abstract_object_pointert(new abstract_objectt(type, top, false)); + if(type.id()==ID_signedbv) + { + return abstract_object_pointert( + new constant_abstract_valuet(type, top, false)); + } + else + { + return abstract_object_pointert(new abstract_objectt(type, top, false)); + } } /*******************************************************************\ @@ -244,11 +267,19 @@ Function: abstract_environmentt::abstract_object_factory \*******************************************************************/ -abstract_objectt *abstract_environmentt::abstract_object_factory( - const typet t, const constant_exprt e) const +abstract_object_pointert abstract_environmentt::abstract_object_factory( + const typet type, const constant_exprt e) const { - assert(t==e.type()); - return new abstract_objectt(e); + assert(type==e.type()); + if(type.id()==ID_signedbv) + { + return abstract_object_pointert( + new constant_abstract_valuet(e)); + } + else + { + return abstract_object_pointert(new abstract_objectt(e)); + } } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index dedd120710c..e8346df6681 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -27,8 +27,8 @@ class abstract_environmentt const typet type, bool top = true) const; // For converting constants in the program // Maybe these two should be compacted to one call... - virtual abstract_objectt *abstract_object_factory( - const typet t, const constant_exprt e) const; + virtual abstract_object_pointert abstract_object_factory( + const typet type, const constant_exprt e) const; virtual bool merge(const abstract_environmentt &env); diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 1a2321f6739..6fcce7fb416 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -130,7 +130,7 @@ Function: abstract_objectt::merge abstract_object_pointert abstract_objectt::merge( const abstract_object_pointert op, bool &out_any_modifications) { - assert(this->type==op->type); + assert(type==op->type); abstract_object_pointert m=abstract_object_pointert(new abstract_objectt(*this)); m->merge_state(abstract_object_pointert(new abstract_objectt(*this)), op); out_any_modifications=!(*m==*this); diff --git a/src/analyses/variable-sensitivity/abstract_value.cpp b/src/analyses/variable-sensitivity/abstract_value.cpp new file mode 100644 index 00000000000..4565a76ea47 --- /dev/null +++ b/src/analyses/variable-sensitivity/abstract_value.cpp @@ -0,0 +1,72 @@ +/*******************************************************************\ + + Module: Analyses Variable Sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ + +#include +#include +#include +#include + +#include "abstract_value.h" + +/*******************************************************************\ + +Function: abstract_valuet::abstract_valuet + + Inputs: + type - the type the abstract_value is representing + + Outputs: + + Purpose: + +\*******************************************************************/ + +abstract_valuet::abstract_valuet(const typet &type): + abstract_objectt(type) +{} + +/*******************************************************************\ + +Function: abstract_valuet::abstract_valuet + + Inputs: + type - the type the abstract_value is representing + top - is the abstract_value starting as top + bottom - is the abstract_value starting as bottom + + Outputs: + + Purpose: Start the abstract object at either top or bottom or neither + Asserts if both top and bottom are true + +\*******************************************************************/ + +abstract_valuet::abstract_valuet(const typet &type, bool top, bool bottom): + abstract_objectt(type, top, bottom) +{} + +/*******************************************************************\ + +Function: abstract_valuet::abstract_valuet + + Inputs: + old - the abstract value to copy from + + Outputs: + + Purpose: + +\*******************************************************************/ + +abstract_valuet::abstract_valuet(const abstract_valuet &old): + abstract_objectt(old) +{} + +abstract_valuet::abstract_valuet(const constant_exprt &expr): + abstract_objectt(expr) +{} diff --git a/src/analyses/variable-sensitivity/abstract_value.h b/src/analyses/variable-sensitivity/abstract_value.h new file mode 100644 index 00000000000..3fa255933d8 --- /dev/null +++ b/src/analyses/variable-sensitivity/abstract_value.h @@ -0,0 +1,26 @@ +/*******************************************************************\ + + Module: Analyses Variable Sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_VALUE_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_VALUE_H + +#include + + +class abstract_valuet:public abstract_objectt +{ +public: + abstract_valuet(const typet &type); + abstract_valuet(const typet &type, bool top, bool bottom); + abstract_valuet(const abstract_valuet &old); + abstract_valuet(const constant_exprt &expr); + + CLONE + MERGE(abstract_objectt) +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_VALUE_H diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp new file mode 100644 index 00000000000..257d737e8d2 --- /dev/null +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -0,0 +1,82 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#include "constant_abstract_value.h" + +#include + +constant_abstract_valuet::constant_abstract_valuet(typet t): + abstract_valuet(t), value() +{} + +constant_abstract_valuet::constant_abstract_valuet(typet t, bool tp, bool bttm): + abstract_valuet(t, tp, bttm), value() +{} + +constant_abstract_valuet::constant_abstract_valuet( + const constant_abstract_valuet &old): + abstract_valuet(old), value(old.value) +{} + +constant_abstract_valuet::constant_abstract_valuet(const constant_exprt e): + abstract_valuet(e), value(e) +{ + top=false; +} + +exprt constant_abstract_valuet::to_constant() const +{ + if(!top && !bottom) + { + return this->value; + } + else + { + return abstract_objectt::to_constant(); + } +} + +bool constant_abstract_valuet::operator==(const abstract_objectt &other) const +{ + // We can cast since should only be using == on same abstract object + const constant_abstract_valuet &other_consant_value= + dynamic_cast(other); + + return abstract_valuet::operator==(other) && value==other_consant_value.value; +} + +void constant_abstract_valuet::output( + std::ostream &out, const ai_baset &ai, const namespacet &ns) +{ + if(!top && !bottom) + { + out << to_constant_expr(value).get_value(); + } + else + { + abstract_objectt::output(out, ai, ns); + } +} + +void constant_abstract_valuet::merge_state( +constant_abstract_value_pointert op1, +constant_abstract_value_pointert op2) +{ + abstract_objectt::merge_state(op1, op2); + if (!top && !bottom) + { + if (op1->value==op2->value) + value=op1->value; + else + { + top=true; + assert(bottom==false); + // Clear out the expression + value=exprt(); + } + } +} diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h new file mode 100644 index 00000000000..af4858955ba --- /dev/null +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -0,0 +1,47 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ABSTRACT_VALUE_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ABSTRACT_VALUE_H + +#include +#include + +class constant_abstract_valuet : public abstract_valuet +{ +private: + typedef sharing_ptrt + constant_abstract_value_pointert; + +public: + constant_abstract_valuet(typet t); + constant_abstract_valuet(typet t, bool tp, bool bttm); + constant_abstract_valuet(const constant_abstract_valuet &old); + constant_abstract_valuet(const constant_exprt e); + + CLONE + MERGE(abstract_valuet) + + virtual exprt to_constant (void) const; + + virtual bool operator==(const abstract_objectt &other) const; + + virtual void output( + std::ostream &out, + const class ai_baset &ai, + const class namespacet &ns); + +protected : + void merge_state( + constant_abstract_value_pointert op1, + constant_abstract_value_pointert op2); + + exprt value; + +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ABSTRACT_VALUE_H From 1eae6e08ac5338e7959387fe3c7d68e33b7fca3f Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Feb 2017 12:18:15 +0000 Subject: [PATCH 025/129] Use variable in the constant_propogation checks --- regression/goto-analyzer/constant_propagation_01/test.desc | 4 ++-- regression/goto-analyzer/constant_propagation_02/test.desc | 4 ++-- regression/goto-analyzer/constant_propagation_03/test.desc | 2 +- regression/goto-analyzer/constant_propagation_04/test.desc | 2 +- regression/goto-analyzer/constant_propagation_05/test.desc | 2 +- regression/goto-analyzer/constant_propagation_06/test.desc | 2 +- regression/goto-analyzer/constant_propagation_07/test.desc | 2 +- regression/goto-analyzer/constant_propagation_08/test.desc | 2 +- regression/goto-analyzer/constant_propagation_09/test.desc | 2 +- regression/goto-analyzer/constant_propagation_10/test.desc | 2 +- regression/goto-analyzer/constant_propagation_11/test.desc | 2 +- regression/goto-analyzer/constant_propagation_12/test.desc | 2 +- regression/goto-analyzer/constant_propagation_13/test.desc | 2 +- regression/goto-analyzer/constant_propagation_14/test.desc | 2 +- regression/goto-analyzer/constant_propagation_15/test.desc | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/regression/goto-analyzer/constant_propagation_01/test.desc b/regression/goto-analyzer/constant_propagation_01/test.desc index a4a79f28ab1..185a69aceee 100644 --- a/regression/goto-analyzer/constant_propagation_01/test.desc +++ b/regression/goto-analyzer/constant_propagation_01/test.desc @@ -1,6 +1,6 @@ -CORE +FUTURE main.c ---constants --simplify out.gb +--variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 5, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_02/test.desc b/regression/goto-analyzer/constant_propagation_02/test.desc index 6a28820a4b0..2bff9d991d7 100644 --- a/regression/goto-analyzer/constant_propagation_02/test.desc +++ b/regression/goto-analyzer/constant_propagation_02/test.desc @@ -1,6 +1,6 @@ -CORE +FUTURE main.c ---constants --simplify out.gb +--variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 6, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_03/test.desc b/regression/goto-analyzer/constant_propagation_03/test.desc index ffe6d41d638..04bd07d905b 100644 --- a/regression/goto-analyzer/constant_propagation_03/test.desc +++ b/regression/goto-analyzer/constant_propagation_03/test.desc @@ -1,6 +1,6 @@ FUTURE main.c ---constants --simplify out.gb +--variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_04/test.desc b/regression/goto-analyzer/constant_propagation_04/test.desc index ffe6d41d638..04bd07d905b 100644 --- a/regression/goto-analyzer/constant_propagation_04/test.desc +++ b/regression/goto-analyzer/constant_propagation_04/test.desc @@ -1,6 +1,6 @@ FUTURE main.c ---constants --simplify out.gb +--variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_05/test.desc b/regression/goto-analyzer/constant_propagation_05/test.desc index e84fdb08b4f..eb40f0011a4 100644 --- a/regression/goto-analyzer/constant_propagation_05/test.desc +++ b/regression/goto-analyzer/constant_propagation_05/test.desc @@ -1,6 +1,6 @@ FUTURE main.c ---constants --verify +--variable --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] file main.c line 12 function main, assertion j!=3: Failure (if reachable)$ diff --git a/regression/goto-analyzer/constant_propagation_06/test.desc b/regression/goto-analyzer/constant_propagation_06/test.desc index 77a7349569f..f8b93dbf345 100644 --- a/regression/goto-analyzer/constant_propagation_06/test.desc +++ b/regression/goto-analyzer/constant_propagation_06/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --verify +--variable --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] file main.c line 11 function main, assertion i\s*<\s*51: Unknown$ diff --git a/regression/goto-analyzer/constant_propagation_07/test.desc b/regression/goto-analyzer/constant_propagation_07/test.desc index c4b03cd8738..b28b7dbf209 100644 --- a/regression/goto-analyzer/constant_propagation_07/test.desc +++ b/regression/goto-analyzer/constant_propagation_07/test.desc @@ -1,6 +1,6 @@ FUTURE main.c ---constants --simplify out.gb +--variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 4, assigns: 10, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_08/test.desc b/regression/goto-analyzer/constant_propagation_08/test.desc index 07a97596c15..4fe007ee5ae 100644 --- a/regression/goto-analyzer/constant_propagation_08/test.desc +++ b/regression/goto-analyzer/constant_propagation_08/test.desc @@ -1,6 +1,6 @@ FUTURE main.c ---constants --simplify out.gb +--variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 2, assigns: 5, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_09/test.desc b/regression/goto-analyzer/constant_propagation_09/test.desc index eebfe27dd49..db1411d762e 100644 --- a/regression/goto-analyzer/constant_propagation_09/test.desc +++ b/regression/goto-analyzer/constant_propagation_09/test.desc @@ -1,6 +1,6 @@ FUTURE main.c ---constants --simplify out.gb +--variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 3, assigns: 4, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_10/test.desc b/regression/goto-analyzer/constant_propagation_10/test.desc index 527325b84bb..2ef09bbe42d 100644 --- a/regression/goto-analyzer/constant_propagation_10/test.desc +++ b/regression/goto-analyzer/constant_propagation_10/test.desc @@ -1,6 +1,6 @@ FUTURE main.c ---constants --verify +--variable --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] file main.c line 10 function main, assertion a\[0\]==2: Failure$ diff --git a/regression/goto-analyzer/constant_propagation_11/test.desc b/regression/goto-analyzer/constant_propagation_11/test.desc index 4e9c8715429..419af4adee4 100644 --- a/regression/goto-analyzer/constant_propagation_11/test.desc +++ b/regression/goto-analyzer/constant_propagation_11/test.desc @@ -1,6 +1,6 @@ FUTURE main.c ---constants --simplify out.gb +--variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 0$ diff --git a/regression/goto-analyzer/constant_propagation_12/test.desc b/regression/goto-analyzer/constant_propagation_12/test.desc index 208b235ccd5..ef80ec9efbe 100644 --- a/regression/goto-analyzer/constant_propagation_12/test.desc +++ b/regression/goto-analyzer/constant_propagation_12/test.desc @@ -1,6 +1,6 @@ FUTURE main.c ---constants --simplify out.gb +--variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 4, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_13/test.desc b/regression/goto-analyzer/constant_propagation_13/test.desc index 2d2e078a424..66c40c2416f 100644 --- a/regression/goto-analyzer/constant_propagation_13/test.desc +++ b/regression/goto-analyzer/constant_propagation_13/test.desc @@ -1,6 +1,6 @@ FUTURE main.c ---constants --verify +--variable --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] file main.c line 9 function main, assertion y==0: Failure (if reachable)$ diff --git a/regression/goto-analyzer/constant_propagation_14/test.desc b/regression/goto-analyzer/constant_propagation_14/test.desc index fc3be910670..c6af06456ba 100644 --- a/regression/goto-analyzer/constant_propagation_14/test.desc +++ b/regression/goto-analyzer/constant_propagation_14/test.desc @@ -1,6 +1,6 @@ FUTURE main.c ---constants --verify +--variable --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] file main.c line 11 function main, assertion a\[0\]==1 || a\[0\]==2: Success$ diff --git a/regression/goto-analyzer/constant_propagation_15/test.desc b/regression/goto-analyzer/constant_propagation_15/test.desc index aba11ba0c06..ac820dfeec6 100644 --- a/regression/goto-analyzer/constant_propagation_15/test.desc +++ b/regression/goto-analyzer/constant_propagation_15/test.desc @@ -1,6 +1,6 @@ FUTURE main.c ---constants --verify +--variable --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] file main.c line 9 function main, assertion a\[0\]==2: Failure$ From 341b61954128a5714099c9ecaeacaeb7c05a0f12 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 21 Feb 2017 10:38:11 +0000 Subject: [PATCH 026/129] Adding debug guarded output to the variable sensitivity domain --- .../abstract_enviroment.cpp | 16 +++++++++---- .../variable_sensitivity_domain.cpp | 23 +++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 8831e4d7028..e2190736cc7 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -13,6 +13,9 @@ #include +#ifdef DEBUG +#include +#endif /*******************************************************************\ @@ -305,6 +308,7 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) // if it is new, or merge with the existing key if it is not present bool modified=false; + for(const auto &entry:env.map) { if(map.find(entry.first)==map.end()) @@ -322,10 +326,7 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) abstract_object_pointert new_object=map[entry.first]->merge( entry.second, object_modified); - if(object_modified) - { - modified=true; - } + modified|=object_modified; map[entry.first]=new_object; } @@ -335,6 +336,9 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) map.erase(entry.first); is_bottom=false; modified=true; +#ifdef DEBUG + std::cout << "Removing " << entry.first.get_identifier() << std::endl; +#endif } } @@ -349,7 +353,11 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) for(const map_keyt &key_to_remove : to_remove) { map.erase(key_to_remove); +#ifdef DEBUG + std::cout << "Removing " << key_to_remove.get_identifier() << std::endl; +#endif } + return modified; } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index e14245b48db..2b91644e1b8 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -13,6 +13,10 @@ Date: April 2016 #include "variable_sensitivity_domain.h" +#ifdef DEBUG +#include +#endif + /*******************************************************************\ @@ -33,6 +37,12 @@ void variable_sensitivity_domaint::transform( ai_baset &ai, const namespacet &ns) { + #ifdef DEBUG + std::cout << "Transform from/to:\n"; + std::cout << from->location_number << " --> " + << to->location_number << std::endl; + #endif + const goto_programt::instructiont &instruction=*from; switch(instruction.type) { @@ -214,15 +224,28 @@ bool variable_sensitivity_domaint::merge( locationt from, locationt to) { + #ifdef DEBUG + std::cout << "Merging from/to:\n " + << from->location_number << " --> " + << to->location_number << std::endl; + #endif + // Use the abstract_environment merge bool any_changes=abstract_state.merge(b.abstract_state); if(abstract_state.get_is_bottom() && !is_set_to_bottom) { is_set_to_bottom=true; +#ifdef DEBUG + std::cout << "\tsetting to bottom" << std::endl; +#endif return true; } else { +#ifdef DEBUG + std::cout << "\tmodified: " << (any_changes ? "true" : "false") + << std::endl; +#endif return any_changes; } } From b10f621b5aabb38682ffcf8415d2a71939298af7 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 21 Feb 2017 15:37:16 +0000 Subject: [PATCH 027/129] Better stub for assigning to non-trivial symbol --- .../abstract_enviroment.cpp | 66 ++++++++++++++++--- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index e2190736cc7..8088594a87c 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -8,6 +8,7 @@ #include "abstract_enviroment.h" #include #include +#include #include #include #include @@ -154,15 +155,11 @@ bool abstract_environmentt::assign( while (s.id() != ID_symbol) { - if (s.id() == ID_index || s.id() == ID_member) + if (s.id() == ID_index || s.id() == ID_member || s.id() == ID_dereference) { stactions.push(s); s = s.op0(); } - else if (s.id() == ID_dereference) - { - // LOL, nope! - } else { // Attempting to assign to something unreasonable @@ -173,19 +170,71 @@ bool abstract_environmentt::assign( const symbol_exprt &symbol_expr(to_symbol_expr(s)); - if (!stactions.empty()) + abstract_object_pointert final_value; + + if(!stactions.empty()) + { + const exprt & next_expr=stactions.top(); + stactions.pop(); + + typedef std::function< + abstract_object_pointert(abstract_object_pointert)> stacion_functiont; + + // Each handler takes the abstract object referenced, copies it, + // writes according to the type of expression (e.g. for ID_member) + // we would (should!) have an abstract_struct_objectt which has a + // write_member which will attempt to update the abstract object for the + // relevant member. This modified abstract object is returned and this + // is inserted back into the map + static std::map handlers= + { + { + ID_index, [&](const abstract_object_pointert lhs_object) + { + // TODO(tkiley): At this point we would cast the AO pointer to an + // array_abstract_objectt + // Then we copy the AO and write to it + // cast_ao->write(popped_stack, index_expr, value) + // Which will continue down the stack + return abstract_object_factory(lhs_object->type, true); + } + }, + { + ID_member, [&](const abstract_object_pointert lhs_object) + { + // TODO(tkiley): Same as with index + return abstract_object_factory(lhs_object->type, true); + } + }, + { + ID_dereference, [&](const abstract_object_pointert lhs_object) + { + // TODO(tkiley): Same as with index + return abstract_object_factory(lhs_object->type, true); + } + } + }; + + // We added something to the stack that we couldn't deal with + assert(handlers.find(next_expr.id())!=handlers.end()); + final_value=handlers[next_expr.id()](value); + } + else { - throw "not yet implemented"; + // We can assign the AO directly to the symbol + final_value=value; } + + // Write the value for the root symbol back into the map if (value->is_top()) { map.erase(symbol_expr); + } else { map[symbol_expr]=value; } - return true; } @@ -453,6 +502,7 @@ bool abstract_environmentt::get_is_top() const } /*******************************************************************\ + Function: abstract_environmentt::output Inputs: From e922362df34ae9828024ed8f9a96644d501030fb Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 21 Feb 2017 16:49:31 +0000 Subject: [PATCH 028/129] Created skeleton classes for the array, pointer, struct These clasess will represent the basis for complex types with helper methods to read and write to/from them. They however will still be just a 2 element abstraction (top or bottom) --- src/analyses/Makefile | 3 + .../array_abstract_object.cpp | 91 ++++++++++++++++++ .../array_abstract_object.h | 25 +++++ .../pointer_abstract_object.cpp | 91 ++++++++++++++++++ .../pointer_abstract_object.h | 28 ++++++ .../struct_abstract_object.cpp | 92 +++++++++++++++++++ .../struct_abstract_object.h | 26 ++++++ 7 files changed, 356 insertions(+) create mode 100644 src/analyses/variable-sensitivity/array_abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/array_abstract_object.h create mode 100644 src/analyses/variable-sensitivity/pointer_abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/pointer_abstract_object.h create mode 100644 src/analyses/variable-sensitivity/struct_abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/struct_abstract_object.h diff --git a/src/analyses/Makefile b/src/analyses/Makefile index d5d5085b4be..14fc6bdadcd 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -27,7 +27,10 @@ SRC = ai.cpp \ variable-sensitivity/abstract_object.cpp \ variable-sensitivity/abstract_enviroment.cpp \ variable-sensitivity/abstract_value.cpp \ + variable-sensitivity/array_abstract_object.cpp \ variable-sensitivity/constant_abstract_value.cpp \ + variable-sensitivity/pointer_abstract_object.cpp \ + variable-sensitivity/struct_abstract_object.cpp \ variable-sensitivity/variable_sensitivity_domain.cpp \ # Empty last line diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp new file mode 100644 index 00000000000..8024fa7c374 --- /dev/null +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -0,0 +1,91 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ + +#include +#include +#include "array_abstract_object.h" + + +/*******************************************************************\ + +Function: array_abstract_objectt::array_abstract_objectt + + Inputs: + type - the type the abstract_object is representing + + Outputs: + + Purpose: + +\*******************************************************************/ + +array_abstract_objectt::array_abstract_objectt(const typet &t): + abstract_objectt(t) +{ + assert(t.id()==ID_array); +} + +/*******************************************************************\ + +Function: array_abstract_objectt::array_abstract_objectt + + Inputs: + type - the type the abstract_object is representing + top - is the abstract_object starting as top + bottom - is the abstract_object starting as bottom + + Outputs: + + Purpose: Start the abstract object at either top or bottom or neither + Asserts if both top and bottom are true + +\*******************************************************************/ + +array_abstract_objectt::array_abstract_objectt( + const typet &t, bool tp, bool bttm): + abstract_objectt(t, tp, bttm) +{ + assert(t.id()==ID_array); +} + +/*******************************************************************\ + +Function: array_abstract_objectt::array_abstract_objectt + + Inputs: + old - the abstract object to copy from + + Outputs: + + Purpose: + +\*******************************************************************/ + +array_abstract_objectt::array_abstract_objectt( + const array_abstract_objectt &old): + abstract_objectt(old) +{} + +/*******************************************************************\ + +Function: array_abstract_objectt::array_abstract_objectt + + Inputs: + expr - the expression to use as the starting pointer for an abstract object + + Outputs: + + Purpose: + +\*******************************************************************/ + +array_abstract_objectt::array_abstract_objectt(const constant_exprt &e): + abstract_objectt(e) +{ + assert(e.type().id()==ID_array); +} diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h new file mode 100644 index 00000000000..bd86eaa006e --- /dev/null +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -0,0 +1,25 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ARRAY_ABSTRACT_OBJECT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ARRAY_ABSTRACT_OBJECT_H + +#include + +class array_abstract_objectt:public abstract_objectt +{ +public: + explicit array_abstract_objectt(const typet &type); + array_abstract_objectt(const typet &type, bool top, bool bottom); + explicit array_abstract_objectt(const array_abstract_objectt &old); + explicit array_abstract_objectt(const constant_exprt &expr); + + CLONE + MERGE(abstract_objectt) +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ARRAY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp new file mode 100644 index 00000000000..ad475b8a957 --- /dev/null +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -0,0 +1,91 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#include +#include + +#include "pointer_abstract_object.h" + + +/*******************************************************************\ + +Function: pointer_abstract_objectt::pointer_abstract_objectt + + Inputs: + type - the type the abstract_object is representing + + Outputs: + + Purpose: + +\*******************************************************************/ + +pointer_abstract_objectt::pointer_abstract_objectt(const typet &t): + abstract_objectt(t) +{ + assert(t.id()==ID_pointer); +} + +/*******************************************************************\ + +Function: pointer_abstract_objectt::pointer_abstract_objectt + + Inputs: + type - the type the abstract_object is representing + top - is the abstract_object starting as top + bottom - is the abstract_object starting as bottom + + Outputs: + + Purpose: Start the abstract object at either top or bottom or neither + Asserts if both top and bottom are true + +\*******************************************************************/ + +pointer_abstract_objectt::pointer_abstract_objectt( + const typet &t, bool tp, bool bttm): + abstract_objectt(t, tp, bttm) +{ + assert(t.id()==ID_pointer); +} + +/*******************************************************************\ + +Function: pointer_abstract_objectt::pointer_abstract_objectt + + Inputs: + old - the abstract object to copy from + + Outputs: + + Purpose: + +\*******************************************************************/ + +pointer_abstract_objectt::pointer_abstract_objectt( + const pointer_abstract_objectt &old): + abstract_objectt(old) +{} + +/*******************************************************************\ + +Function: pointer_abstract_objectt::pointer_abstract_objectt + + Inputs: + expr - the expression to use as the starting pointer for an abstract object + + Outputs: + + Purpose: + +\*******************************************************************/ + +pointer_abstract_objectt::pointer_abstract_objectt(const constant_exprt &e): + abstract_objectt(e) +{ + assert(e.type().id()==ID_pointer); +} diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h new file mode 100644 index 00000000000..d8a8074d3c0 --- /dev/null +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -0,0 +1,28 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_POINTER_ABSTRACT_OBJECT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_POINTER_ABSTRACT_OBJECT_H + +#include + +class typet; +class constant_exprt; + +class pointer_abstract_objectt:public abstract_objectt +{ +public: + explicit pointer_abstract_objectt(const typet &type); + pointer_abstract_objectt(const typet &type, bool top, bool bottom); + explicit pointer_abstract_objectt(const pointer_abstract_objectt &old); + explicit pointer_abstract_objectt(const constant_exprt &expr); + + CLONE + MERGE(abstract_objectt) +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_POINTER_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp new file mode 100644 index 00000000000..301bf7a31ba --- /dev/null +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -0,0 +1,92 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ + +#include +#include + +#include "struct_abstract_object.h" + + +/*******************************************************************\ + +Function: struct_abstract_objectt::struct_abstract_objectt + + Inputs: + type - the type the abstract_object is representing + + Outputs: + + Purpose: + +\*******************************************************************/ + +struct_abstract_objectt::struct_abstract_objectt(const typet &t): + abstract_objectt(t) +{ + assert(t.id()==ID_struct); +} + +/*******************************************************************\ + +Function: struct_abstract_objectt::struct_abstract_objectt + + Inputs: + type - the type the abstract_object is representing + top - is the abstract_object starting as top + bottom - is the abstract_object starting as bottom + + Outputs: + + Purpose: Start the abstract object at either top or bottom or neither + Asserts if both top and bottom are true + +\*******************************************************************/ + +struct_abstract_objectt::struct_abstract_objectt( + const typet &t, bool tp, bool bttm): + abstract_objectt(t, tp, bttm) +{ + assert(t.id()==ID_struct); +} + +/*******************************************************************\ + +Function: struct_abstract_objectt::struct_abstract_objectt + + Inputs: + old - the abstract object to copy from + + Outputs: + + Purpose: + +\*******************************************************************/ + +struct_abstract_objectt::struct_abstract_objectt( + const struct_abstract_objectt &old): + abstract_objectt(old) +{} + +/*******************************************************************\ + +Function: struct_abstract_objectt::struct_abstract_objectt + + Inputs: + expr - the expression to use as the starting pointer for an abstract object + + Outputs: + + Purpose: + +\*******************************************************************/ + +struct_abstract_objectt::struct_abstract_objectt(const constant_exprt &e): + abstract_objectt(e) +{ + assert(e.type().id()==ID_struct); +} diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h new file mode 100644 index 00000000000..170c0865d64 --- /dev/null +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -0,0 +1,26 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ + +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H + +#include + +class struct_abstract_objectt:public abstract_objectt +{ +public: + explicit struct_abstract_objectt(const typet &type); + struct_abstract_objectt(const typet &type, bool top, bool bottom); + explicit struct_abstract_objectt(const struct_abstract_objectt &old); + explicit struct_abstract_objectt(const constant_exprt &expr); + + CLONE + MERGE(abstract_objectt) +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H From b5fda65c14e061be92813a5b61e81824a45ca870 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 21 Feb 2017 18:04:14 +0000 Subject: [PATCH 029/129] Adding a 2 element implemention of sturct abstract object --- .../abstract_enviroment.cpp | 36 ++++++----- .../struct_abstract_object.cpp | 59 +++++++++++++++++++ .../struct_abstract_object.h | 13 ++++ 3 files changed, 93 insertions(+), 15 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 8088594a87c..b7d1f186a0d 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -62,15 +63,12 @@ abstract_object_pointert abstract_environmentt::eval( { ID_member, [&](const exprt &expr) { -#if 0 member_exprt member_expr(to_member_expr(expr)); -#endif - // TODO(tkiley): eval the compound to (hopefully) get an - // abstract_struct_objectt then use that to get an AO for a specific - // component. - // For now, just return top - return abstract_object_pointert( - new abstract_objectt(expr.type(), true, false)); + sharing_ptrt struct_abstract_object= + std::dynamic_pointer_cast( + eval(member_expr.compound())); + + return struct_abstract_object->read_component(*this, member_expr); } }, { @@ -178,7 +176,8 @@ bool abstract_environmentt::assign( stactions.pop(); typedef std::function< - abstract_object_pointert(abstract_object_pointert)> stacion_functiont; + abstract_object_pointert( + abstract_object_pointert, std::stack)> stacion_functiont; // Each handler takes the abstract object referenced, copies it, // writes according to the type of expression (e.g. for ID_member) @@ -189,7 +188,8 @@ bool abstract_environmentt::assign( static std::map handlers= { { - ID_index, [&](const abstract_object_pointert lhs_object) + ID_index, [&]( + const abstract_object_pointert lhs_object, std::stack stack) { // TODO(tkiley): At this point we would cast the AO pointer to an // array_abstract_objectt @@ -200,14 +200,20 @@ bool abstract_environmentt::assign( } }, { - ID_member, [&](const abstract_object_pointert lhs_object) + ID_member, [&]( + const abstract_object_pointert lhs_object, std::stack stack) { - // TODO(tkiley): Same as with index - return abstract_object_factory(lhs_object->type, true); + sharing_ptrt struct_abstract_object= + std::dynamic_pointer_cast(lhs_object); + sharing_ptrt modified_struct= + struct_abstract_object->write_component( + *this, stactions, to_member_expr(next_expr)); + return modified_struct; } }, { - ID_dereference, [&](const abstract_object_pointert lhs_object) + ID_dereference, [&]( + const abstract_object_pointert lhs_object, std::stack stack) { // TODO(tkiley): Same as with index return abstract_object_factory(lhs_object->type, true); @@ -217,7 +223,7 @@ bool abstract_environmentt::assign( // We added something to the stack that we couldn't deal with assert(handlers.find(next_expr.id())!=handlers.end()); - final_value=handlers[next_expr.id()](value); + final_value=handlers[next_expr.id()](value, stactions); } else { diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index 301bf7a31ba..0c58ac59b26 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "struct_abstract_object.h" @@ -90,3 +91,61 @@ struct_abstract_objectt::struct_abstract_objectt(const constant_exprt &e): { assert(e.type().id()==ID_struct); } + +/*******************************************************************\ + +Function: struct_abstract_objectt::read_component + + Inputs: + environment - the abstract environment + member_expr - the expression uses to access a specific component + + Outputs: The abstract object representing the value of that component. For + this abstraction this will always be top since we are not tracking + the struct. + + Purpose: A helper function to evaluate the abstract object contained + within a struct. More precise abstractions may override this + to return more precise results. + +\*******************************************************************/ + +abstract_object_pointert struct_abstract_objectt::read_component( + const abstract_environmentt &environment, const member_exprt &member_expr) +{ + // Presumably reading from a bottom struct is bad? + assert(!bottom); + return environment.abstract_object_factory(member_expr.type(), true); +} + +/*******************************************************************\ + +Function: struct_abstract_objectt::write_component + + Inputs: + environment - the abstract environment + stack - the remaining stack of expressions on the LHS to evaluate + member_expr - the expression uses to access a specific component + + Outputs: The struct_abstract_objectt representing the result of writing + to a specific component. In this case this will always be top + as we are not tracking the value of this struct. + + Purpose: A helper function to evaluate writing to a component of a struct. + More precise abstractions may override this to + update what they are storing for a specific component. + +\*******************************************************************/ + +sharing_ptrt struct_abstract_objectt::write_component( + const abstract_environmentt &environment, + const std::stack stack, + const member_exprt &member_expr) +{ + // Return a copy of this set to top + sharing_ptrt copy( + new struct_abstract_objectt(*this)); + copy->top=true; + copy->bottom=false; + return copy; +} diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index 170c0865d64..84a3cf5b7ce 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -9,8 +9,12 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H +#include #include +class abstract_environmentt; +class member_exprt; + class struct_abstract_objectt:public abstract_objectt { public: @@ -21,6 +25,15 @@ class struct_abstract_objectt:public abstract_objectt CLONE MERGE(abstract_objectt) + + // struct interface + virtual abstract_object_pointert read_component( + const abstract_environmentt &environment, const member_exprt &member_expr); + + virtual sharing_ptrt write_component( + const abstract_environmentt &environment, + const std::stack stack, + const member_exprt &member_expr); }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H From b6ab6e6fe9c2af8e1497662e145a48246b3814cc Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 22 Feb 2017 10:31:19 +0000 Subject: [PATCH 030/129] Modifications to struct_abstract_object Made so the read returns a bottom element if it is bottom. Made the write return itself if true to faciliate sharing. --- .../abstract_enviroment.cpp | 4 +-- .../abstract_enviroment.h | 2 +- .../struct_abstract_object.cpp | 25 ++++++++++++------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index b7d1f186a0d..d65a6d60d09 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -296,13 +296,13 @@ Function: abstract_environmentt::abstract_object_factory \*******************************************************************/ abstract_object_pointert abstract_environmentt::abstract_object_factory( - const typet type, bool top) const + const typet type, bool top, bool bottom) const { // TODO (tkiley): Here we should look at some config file if(type.id()==ID_signedbv) { return abstract_object_pointert( - new constant_abstract_valuet(type, top, false)); + new constant_abstract_valuet(type, top, bottom)); } else { diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index e8346df6681..4fb789b88c2 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -24,7 +24,7 @@ class abstract_environmentt virtual bool assume(const exprt &expr); virtual abstract_object_pointert abstract_object_factory( - const typet type, bool top = true) const; + const typet type, bool top=true, bool bottom=false) const; // For converting constants in the program // Maybe these two should be compacted to one call... virtual abstract_object_pointert abstract_object_factory( diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index 0c58ac59b26..acf481ef23b 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -113,9 +113,10 @@ Function: struct_abstract_objectt::read_component abstract_object_pointert struct_abstract_objectt::read_component( const abstract_environmentt &environment, const member_exprt &member_expr) { - // Presumably reading from a bottom struct is bad? - assert(!bottom); - return environment.abstract_object_factory(member_expr.type(), true); + // If we are bottom then so are the components + // otherwise the components could be anything + return environment.abstract_object_factory( + member_expr.type(), !is_bottom(), is_bottom()); } /*******************************************************************\ @@ -142,10 +143,16 @@ sharing_ptrt struct_abstract_objectt::write_component( const std::stack stack, const member_exprt &member_expr) { - // Return a copy of this set to top - sharing_ptrt copy( - new struct_abstract_objectt(*this)); - copy->top=true; - copy->bottom=false; - return copy; + if(is_top()) + { + return sharing_ptrt(this); + } + else + { + sharing_ptrt copy( + new struct_abstract_objectt(*this)); + copy->top=false; + copy->bottom=true; + return copy; + } } From d4cb43ddbe69ccdab0a13d7a51eebc9a19735cc8 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 22 Feb 2017 11:17:38 +0000 Subject: [PATCH 031/129] Readded broken protected Can't use type directly when accessing a parent type so need to use the getter. --- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 4 ++-- src/analyses/variable-sensitivity/abstract_object.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index d65a6d60d09..a27aba2853f 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -196,7 +196,7 @@ bool abstract_environmentt::assign( // Then we copy the AO and write to it // cast_ao->write(popped_stack, index_expr, value) // Which will continue down the stack - return abstract_object_factory(lhs_object->type, true); + return abstract_object_factory(lhs_object->get_type(), true); } }, { @@ -216,7 +216,7 @@ bool abstract_environmentt::assign( const abstract_object_pointert lhs_object, std::stack stack) { // TODO(tkiley): Same as with index - return abstract_object_factory(lhs_object->type, true); + return abstract_object_factory(lhs_object->get_type(), true); } } }; diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index f01b6fe7ca6..3d3b18747db 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -28,7 +28,7 @@ class constant_exprt; const abstract_object_pointert op, \ bool &out_any_modifications) \ {\ - assert(this->type==op->type); \ + assert(type==op->get_type()); \ typedef std::remove_const::type \ >::type current_typet; \ \ @@ -88,7 +88,7 @@ class abstract_objectt virtual bool operator==(const abstract_objectt &other) const; - //protected +protected: typet type; bool top; bool bottom; From a3654e3d92ed70b3ccb06ba0656cd36793bcde32 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 22 Feb 2017 14:09:04 +0000 Subject: [PATCH 032/129] Implementation of simplify We try and evaluate conditions and replace them with wether they are true or not. --- .../variable_sensitivity_domain.cpp | 37 +++++++++++++++++++ .../variable_sensitivity_domain.h | 6 ++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 2b91644e1b8..82eac57bca7 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -250,6 +250,43 @@ bool variable_sensitivity_domaint::merge( } } +/*******************************************************************\ + +Function: variable_sensitivity_domaint::ai_simplify + + Inputs: + condition - the expression to evaluate to true or false + ns - the namespace + lhs - is the expression on the left hand side + + Outputs: True if simplified the condition. False otherwise. condition + will be updated with the simplified condition if it has worked + + Purpose: To resolve a condition down to a possibly known boolean value + +\*******************************************************************/ + +bool variable_sensitivity_domaint::ai_simplify( + exprt &condition, const namespacet &ns, const bool lhs) const +{ + if (lhs) + return false; + else + { + sharing_ptrt res = abstract_state.eval(condition); + exprt c = res->to_constant(); + + if (c.id() == ID_nil) + return false; + else + { + bool b = (condition!=c); + condition = c; + return b; + } + } +} + bool variable_sensitivity_domaint::is_bottom() const { return is_set_to_bottom && abstract_state.get_is_bottom(); diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index db21dd24512..51841bc3b62 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -43,6 +43,11 @@ class variable_sensitivity_domaint : public ai_domain_baset locationt from, locationt to); + bool ai_simplify( + exprt &condition, + const namespacet &ns, + const bool lhs=false) const override; + bool is_bottom() const override; bool is_top() const override; @@ -50,7 +55,6 @@ class variable_sensitivity_domaint : public ai_domain_baset abstract_environmentt abstract_state; bool is_set_to_bottom; - }; #endif // CPROVER_GOTO_ANALYZER_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H // NOLINT(*) From 2d8cb48439b02d541664b69a3fe30c44338c58f5 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 22 Feb 2017 15:54:04 +0000 Subject: [PATCH 033/129] Don't use static for the map as means wrong this is captured --- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index a27aba2853f..647d01e27ff 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -36,7 +36,7 @@ abstract_object_pointert abstract_environmentt::eval( const exprt &expr) const { typedef std::function eval_handlert; - static std::map handlers= + std::map handlers= { { ID_symbol, [&](const exprt &expr) From e562e9df5a6793109d28b8104663157be46fdec1 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 22 Feb 2017 15:54:21 +0000 Subject: [PATCH 034/129] Added handler for logical == expression --- .../abstract_enviroment.cpp | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 647d01e27ff..cc14f0b8338 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -110,6 +110,12 @@ abstract_object_pointert abstract_environmentt::eval( return abstract_object_pointert( new abstract_objectt(expr.type(), true, false)); } + }, + { + ID_equal, [&](const exprt &expr) + { + return eval_logical(expr); + } } }; #if 0 @@ -542,7 +548,45 @@ void abstract_environmentt::output( abstract_object_pointert abstract_environmentt::eval_logical( const exprt &e) const { - throw "not implemented"; + typedef std::function eval_handlert; + std::map handlers= + { + { + ID_equal, [&](const exprt &expr) + { + abstract_object_pointert lhs=eval(expr.op0()); + abstract_object_pointert rhs=eval(expr.op1()); + + const exprt &lhs_value=lhs->to_constant(); + const exprt &rhs_value=rhs->to_constant(); + + if(lhs_value.id()==ID_nil || rhs_value.id()==ID_nil) + { + // One or both of the values is unknown so therefore we can't conclude + // whether this is true or false + return abstract_object_pointert( + new abstract_objectt(expr.type(), true, false)); + } + else + { + bool logical_result=lhs_value==rhs_value; + if(logical_result) + { + return abstract_object_pointert( + new constant_abstract_valuet(true_exprt())); + } + else + { + return abstract_object_pointert( + new constant_abstract_valuet(false_exprt())); + } + } + } + } + }; + + assert(handlers.find(e.id())!=handlers.end()); + return handlers[e.id()](e); } abstract_object_pointert abstract_environmentt::eval_rest(const exprt &e) const From 5257140448c6fbcc87c6be4813f16a5ade966be0 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Feb 2017 09:24:37 +0000 Subject: [PATCH 035/129] Cleaned up the variable sensitivity framework Talked through with Dan what I had done so far and made some simplifications and improvments to how it works. --- .../abstract_enviroment.cpp | 71 ++++++++++--------- .../variable-sensitivity/abstract_object.cpp | 26 ++----- .../variable-sensitivity/abstract_object.h | 7 +- .../constant_abstract_value.cpp | 27 ++++--- .../constant_abstract_value.h | 4 +- .../variable_sensitivity_domain.cpp | 23 +----- .../variable_sensitivity_domain.h | 1 - 7 files changed, 61 insertions(+), 98 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index cc14f0b8338..64fdca98e7a 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -35,6 +35,7 @@ Function: abstract_environmentt::eval abstract_object_pointert abstract_environmentt::eval( const exprt &expr) const { + assert(!is_bottom); typedef std::function eval_handlert; std::map handlers= { @@ -368,58 +369,62 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) // for each entry in the incoming environment we need to either add it // if it is new, or merge with the existing key if it is not present - bool modified=false; - for(const auto &entry:env.map) + + if(is_bottom) + { + *this=env; + return !env.is_bottom; + } + else if(env.is_bottom) + { + return false; + } + else { - if(map.find(entry.first)==map.end()) + bool modified=false; + for(const auto &entry:env.map) { - // We only add new stuff if we are bottom - if(is_bottom) + if(map.find(entry.first)!=map.end()) { - map[entry.first] = entry.second; - modified=true; - } - } - else - { - bool object_modified=false; - abstract_object_pointert new_object=map[entry.first]->merge( - entry.second, object_modified); + bool object_modified=false; + abstract_object_pointert new_object=map[entry.first]->merge( + entry.second, object_modified); modified|=object_modified; - map[entry.first]=new_object; + map[entry.first]=new_object; - } + } - if(map[entry.first]->is_top()) - { - map.erase(entry.first); - is_bottom=false; - modified=true; + if(map[entry.first]->is_top()) + { + map.erase(entry.first); + modified=true; #ifdef DEBUG std::cout << "Removing " << entry.first.get_identifier() << std::endl; #endif + } } - } - std::vector to_remove; - for(const auto &entry : map) - { - if(env.map.find(entry.first)==env.map.end()) + std::vector to_remove; + for(const auto &entry : map) { - to_remove.push_back(entry.first); + if(env.map.find(entry.first)==env.map.end()) + { + to_remove.push_back(entry.first); + } } - } - for(const map_keyt &key_to_remove : to_remove) - { - map.erase(key_to_remove); + for(const map_keyt &key_to_remove : to_remove) + { + map.erase(key_to_remove); #ifdef DEBUG std::cout << "Removing " << key_to_remove.get_identifier() << std::endl; #endif - } + modified=true; + } - return modified; + return modified; + } } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 6fcce7fb416..aab8cd153fb 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -105,12 +105,14 @@ Function: abstract_objectt::merge_state \*******************************************************************/ -void abstract_objectt::merge_state( +bool abstract_objectt::merge_state( const abstract_object_pointert op1, const abstract_object_pointert op2) { top=op1->top||op2->top; bottom=op1->bottom && op2->bottom; + assert(!(top && bottom)); + return top!=op1->top || bottom!=op1->bottom; } /*******************************************************************\ @@ -132,8 +134,7 @@ abstract_object_pointert abstract_objectt::merge( { assert(type==op->type); abstract_object_pointert m=abstract_object_pointert(new abstract_objectt(*this)); - m->merge_state(abstract_object_pointert(new abstract_objectt(*this)), op); - out_any_modifications=!(*m==*this); + out_any_modifications=m->merge_state(abstract_object_pointert(this), op); return m; } @@ -224,22 +225,3 @@ void abstract_objectt::output( out << "Unknown"; } } - -/*******************************************************************\ - -Function: abstract_objectt::operator== - - Inputs: - other - the abstract_object to compare - - Outputs: Returns true if the two abstract objects are equivalent - - Purpose: Check to AOs are representing the same value according to - their sensitivity. - -\*******************************************************************/ - -bool abstract_objectt::operator==(const abstract_objectt &other) const -{ - return top==other.top && bottom==other.bottom; -} diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 3d3b18747db..96ab1e417a8 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -42,8 +42,7 @@ class constant_exprt; current_type_ptrt m=current_type_ptrt(new current_typet(*this)); \ if (n!= NULL) \ { \ - m->merge_state(current_type_ptrt(new current_typet(*this)), n); \ - out_any_modifications=!(*this==*m); \ + out_any_modifications=m->merge_state(current_type_ptrt(new current_typet(*this)), n); \ return m; \ } \ else \ @@ -71,7 +70,7 @@ class abstract_objectt virtual bool is_bottom() const; // Sets the state of this object - void merge_state( + bool merge_state( const abstract_object_pointert op1, const abstract_object_pointert op2); // This is both the interface and the base case of the recursion @@ -86,8 +85,6 @@ class abstract_objectt CLONE - virtual bool operator==(const abstract_objectt &other) const; - protected: typet type; bool top; diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index 257d737e8d2..2b855fad2f0 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -40,15 +40,6 @@ exprt constant_abstract_valuet::to_constant() const } } -bool constant_abstract_valuet::operator==(const abstract_objectt &other) const -{ - // We can cast since should only be using == on same abstract object - const constant_abstract_valuet &other_consant_value= - dynamic_cast(other); - - return abstract_valuet::operator==(other) && value==other_consant_value.value; -} - void constant_abstract_valuet::output( std::ostream &out, const ai_baset &ai, const namespacet &ns) { @@ -62,21 +53,29 @@ void constant_abstract_valuet::output( } } -void constant_abstract_valuet::merge_state( -constant_abstract_value_pointert op1, -constant_abstract_value_pointert op2) +bool constant_abstract_valuet::merge_state( + constant_abstract_value_pointert op1, + constant_abstract_value_pointert op2) { - abstract_objectt::merge_state(op1, op2); + bool parent_merge_change=abstract_objectt::merge_state(op1, op2); if (!top && !bottom) { if (op1->value==op2->value) + { value=op1->value; - else + return false; + } + else // values different { top=true; assert(bottom==false); // Clear out the expression value=exprt(); + return !op1->top; } } + else // either top or bottom + { + return parent_merge_change; + } } diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index af4858955ba..0f17cb325fd 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -28,15 +28,13 @@ class constant_abstract_valuet : public abstract_valuet virtual exprt to_constant (void) const; - virtual bool operator==(const abstract_objectt &other) const; - virtual void output( std::ostream &out, const class ai_baset &ai, const class namespacet &ns); protected : - void merge_state( + bool merge_state( constant_abstract_value_pointert op1, constant_abstract_value_pointert op2); diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 82eac57bca7..ec261848dbe 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -168,7 +168,6 @@ Function: variable_sensitivity_domaint::make_bottom void variable_sensitivity_domaint::make_bottom() { abstract_state.make_bottom(); - return; } @@ -202,8 +201,7 @@ Function: variable_sensitivity_domaint::make_entry \*******************************************************************/ void variable_sensitivity_domaint::make_entry() { - abstract_state.make_bottom(); - is_set_to_bottom=false; + abstract_state.make_top(); } /*******************************************************************\ @@ -232,22 +230,7 @@ bool variable_sensitivity_domaint::merge( // Use the abstract_environment merge bool any_changes=abstract_state.merge(b.abstract_state); - if(abstract_state.get_is_bottom() && !is_set_to_bottom) - { - is_set_to_bottom=true; -#ifdef DEBUG - std::cout << "\tsetting to bottom" << std::endl; -#endif - return true; - } - else - { -#ifdef DEBUG - std::cout << "\tmodified: " << (any_changes ? "true" : "false") - << std::endl; -#endif - return any_changes; - } + return any_changes; } /*******************************************************************\ @@ -289,7 +272,7 @@ bool variable_sensitivity_domaint::ai_simplify( bool variable_sensitivity_domaint::is_bottom() const { - return is_set_to_bottom && abstract_state.get_is_bottom(); + return abstract_state.get_is_bottom(); } bool variable_sensitivity_domaint::is_top() const diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 51841bc3b62..8d6b89d0e06 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -53,7 +53,6 @@ class variable_sensitivity_domaint : public ai_domain_baset private: abstract_environmentt abstract_state; - bool is_set_to_bottom; }; From 292673b15aa318144a8b0be56530626f21067190 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Feb 2017 11:27:50 +0000 Subject: [PATCH 036/129] Corrected the logic for non-trivial assigns --- .../abstract_enviroment.cpp | 23 +++++++++++++------ .../variable-sensitivity/abstract_object.cpp | 8 +++++++ .../variable-sensitivity/abstract_object.h | 4 ++++ .../struct_abstract_object.cpp | 3 ++- .../struct_abstract_object.h | 3 ++- 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 64fdca98e7a..a365ed9391b 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -184,7 +184,10 @@ bool abstract_environmentt::assign( typedef std::function< abstract_object_pointert( - abstract_object_pointert, std::stack)> stacion_functiont; + abstract_object_pointert, // The symbol we are modifying + std::stack, // The remaining stack + abstract_object_pointert)> // The value we are writing. + stacion_functiont; // Each handler takes the abstract object referenced, copies it, // writes according to the type of expression (e.g. for ID_member) @@ -192,11 +195,13 @@ bool abstract_environmentt::assign( // write_member which will attempt to update the abstract object for the // relevant member. This modified abstract object is returned and this // is inserted back into the map - static std::map handlers= + std::map handlers= { { ID_index, [&]( - const abstract_object_pointert lhs_object, std::stack stack) + const abstract_object_pointert lhs_object, + std::stack stack, + abstract_object_pointert rhs_object) { // TODO(tkiley): At this point we would cast the AO pointer to an // array_abstract_objectt @@ -208,19 +213,23 @@ bool abstract_environmentt::assign( }, { ID_member, [&]( - const abstract_object_pointert lhs_object, std::stack stack) + const abstract_object_pointert lhs_object, + std::stack stack, + abstract_object_pointert rhs_object) { sharing_ptrt struct_abstract_object= std::dynamic_pointer_cast(lhs_object); sharing_ptrt modified_struct= struct_abstract_object->write_component( - *this, stactions, to_member_expr(next_expr)); + *this, stactions, to_member_expr(next_expr), rhs_object); return modified_struct; } }, { ID_dereference, [&]( - const abstract_object_pointert lhs_object, std::stack stack) + const abstract_object_pointert lhs_object, + std::stack stack, + abstract_object_pointert rhs_object) { // TODO(tkiley): Same as with index return abstract_object_factory(lhs_object->get_type(), true); @@ -230,7 +239,7 @@ bool abstract_environmentt::assign( // We added something to the stack that we couldn't deal with assert(handlers.find(next_expr.id())!=handlers.end()); - final_value=handlers[next_expr.id()](value, stactions); + final_value=handlers[next_expr.id()](map[symbol_expr], stactions, value); } else { diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index aab8cd153fb..f905f0cc902 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -138,6 +138,14 @@ abstract_object_pointert abstract_objectt::merge( return m; } +#if 0 +abstract_object_pointert abstract_objectt::expression_transform_logical( + const exprt &expr, abstract_environmentt &environment) +{ + +} +#endif + /*******************************************************************\ Function: abstract_objectt::is_top diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 96ab1e417a8..c2d02574ca0 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -10,6 +10,7 @@ class typet; class constant_exprt; +class abstract_environmentt; #include #include @@ -78,6 +79,9 @@ class abstract_objectt virtual abstract_object_pointert merge( const abstract_object_pointert op, bool &out_any_modifications); + // Interface for transforms + //abstract_object_pointert expression_transform_logical(const exprt &expr, abstract_environmentt &environment); + virtual exprt to_constant() const; virtual void output( diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index acf481ef23b..b3b0ab8933d 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -141,7 +141,8 @@ Function: struct_abstract_objectt::write_component sharing_ptrt struct_abstract_objectt::write_component( const abstract_environmentt &environment, const std::stack stack, - const member_exprt &member_expr) + const member_exprt &member_expr, + const abstract_object_pointert value) { if(is_top()) { diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index 84a3cf5b7ce..aacb0c26e4b 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -33,7 +33,8 @@ class struct_abstract_objectt:public abstract_objectt virtual sharing_ptrt write_component( const abstract_environmentt &environment, const std::stack stack, - const member_exprt &member_expr); + const member_exprt &member_expr, + const abstract_object_pointert value); }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H From c41d65f0e75d1ce998da4475d0998e8722e8bf29 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Feb 2017 12:26:51 +0000 Subject: [PATCH 037/129] Fixied potential dangling pointer in the struct abstract oject --- src/analyses/variable-sensitivity/struct_abstract_object.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index b3b0ab8933d..1e2031a36dc 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -127,6 +127,7 @@ Function: struct_abstract_objectt::write_component environment - the abstract environment stack - the remaining stack of expressions on the LHS to evaluate member_expr - the expression uses to access a specific component + value - the value we are trying to write to the component Outputs: The struct_abstract_objectt representing the result of writing to a specific component. In this case this will always be top @@ -146,7 +147,8 @@ sharing_ptrt struct_abstract_objectt::write_component( { if(is_top()) { - return sharing_ptrt(this); + return sharing_ptrt( + new struct_abstract_objectt(*this)); } else { From e26e7c3c22ec4479cde98814cc850c20a1a48037 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Feb 2017 14:00:28 +0000 Subject: [PATCH 038/129] Basic implementations for abstract pointer and abstract array --- .../abstract_enviroment.cpp | 54 ++++++-------- .../array_abstract_object.cpp | 74 +++++++++++++++++++ .../array_abstract_object.h | 15 ++++ .../pointer_abstract_object.cpp | 69 +++++++++++++++++ .../pointer_abstract_object.h | 14 ++++ 5 files changed, 196 insertions(+), 30 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index a365ed9391b..bb28ebb1e82 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include @@ -87,35 +89,23 @@ abstract_object_pointert abstract_environmentt::eval( { ID_dereference, [&](const exprt &expr) { - #if 0 dereference_exprt dereference(to_dereference_expr(expr)); - #endif - // TODO(tkiley): eval the pointer to (hopefully) get an - // abstract_pointer_objectt then use that to get an AO for a specific - // value. - // For now, just return top - return abstract_object_pointert( - new abstract_objectt(expr.type(), true, false)); + sharing_ptrt pointer_abstract_object= + std::dynamic_pointer_cast( + eval(dereference.pointer())); + + return pointer_abstract_object->read_dereference(*this); } }, { ID_index, [&](const exprt &expr) { -#if 0 index_exprt index_expr(to_index_expr(expr)); -#endif - // TODO(tkiley): eval the array to (hopefully) get an - // abstract_array_objectt then use that to get an AO for a specific - // index. - // For now, just return top - return abstract_object_pointert( - new abstract_objectt(expr.type(), true, false)); - } - }, - { - ID_equal, [&](const exprt &expr) - { - return eval_logical(expr); + sharing_ptrt array_abstract_object= + std::dynamic_pointer_cast( + eval(index_expr.array())); + + return array_abstract_object->read_index(*this, index_expr); } } }; @@ -203,12 +193,12 @@ bool abstract_environmentt::assign( std::stack stack, abstract_object_pointert rhs_object) { - // TODO(tkiley): At this point we would cast the AO pointer to an - // array_abstract_objectt - // Then we copy the AO and write to it - // cast_ao->write(popped_stack, index_expr, value) - // Which will continue down the stack - return abstract_object_factory(lhs_object->get_type(), true); + sharing_ptrt array_abstract_object= + std::dynamic_pointer_cast(lhs_object); + sharing_ptrt modified_array= + array_abstract_object->write_index( + *this, stactions, to_index_expr(next_expr), rhs_object, false); + return modified_array; } }, { @@ -231,8 +221,12 @@ bool abstract_environmentt::assign( std::stack stack, abstract_object_pointert rhs_object) { - // TODO(tkiley): Same as with index - return abstract_object_factory(lhs_object->get_type(), true); + sharing_ptrt pointer_abstract_object= + std::dynamic_pointer_cast(lhs_object); + sharing_ptrt modified_pointer= + pointer_abstract_object->write_dereference( + *this, stactions, rhs_object, false); + return modified_pointer; } } }; diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 8024fa7c374..99430ad9044 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "array_abstract_object.h" @@ -89,3 +90,76 @@ array_abstract_objectt::array_abstract_objectt(const constant_exprt &e): { assert(e.type().id()==ID_array); } + +/*******************************************************************\ + +Function: array_abstract_objectt::read_index + + Inputs: + env - the environment + index - the expression used to access the specific value in the array + + Outputs: An abstract object representing the value in the array + + Purpose: A helper function to read elements from an array. More precise + abstractions may override this to provide more precise results. + +\*******************************************************************/ + +abstract_object_pointert array_abstract_objectt::read_index( + const abstract_environmentt &env, const index_exprt &index) const +{ + array_typet array_type(to_array_type(type)); + const typet &subtype=array_type.subtype(); + + // if we are bottom then so are the values in the array + // otherwise the values are top + return env.abstract_object_factory(subtype, !is_bottom(), is_bottom()); +} + +/*******************************************************************\ + +Function: abstract_object_pointert array_abstract_objectt + + Inputs: + environment - the abstract environment + stack - the remaining stack of expressions on the LHS to evaluate + index_expr - the expression uses to access a specific index + value - the value we are trying to assign to that value in the array + merging_write - ? + + Outputs: The struct_abstract_objectt representing the result of writing + to a specific component. In this case this will always be top + as we are not tracking the value of this struct. + + Purpose: A helper function to evaluate writing to a component of a struct. + More precise abstractions may override this to + update what they are storing for a specific component. + +\*******************************************************************/ + +sharing_ptrt array_abstract_objectt::write_index( + abstract_environmentt &environment, + const std::stack stack, + const index_exprt &index_expr, + const abstract_object_pointert value, + bool merging_write) +{ + // TODO(tkiley): Should this in fact havoc since we can't verify + // that we are not writing past the end of the array - Martin said + // default should be not to, but perhaps for soundness the base class should + // havoc and the default should derive from this. + if(is_top()) + { + return sharing_ptrt( + new array_abstract_objectt(*this)); + } + else + { + sharing_ptrt copy( + new array_abstract_objectt(*this)); + copy->top=false; + copy->bottom=true; + return copy; + } +} diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index bd86eaa006e..3af79165863 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -8,8 +8,14 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ARRAY_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ARRAY_ABSTRACT_OBJECT_H +#include #include +class abstract_environmentt; +class index_exprt; + + + class array_abstract_objectt:public abstract_objectt { public: @@ -20,6 +26,15 @@ class array_abstract_objectt:public abstract_objectt CLONE MERGE(abstract_objectt) + + virtual abstract_object_pointert read_index( + const abstract_environmentt &env, const index_exprt &index) const; + + virtual sharing_ptrt write_index( + abstract_environmentt &environment, + const std::stack stack, const index_exprt &index_expr, + const abstract_object_pointert value, + bool merging_write); }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ARRAY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index ad475b8a957..49c221d349a 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -8,6 +8,8 @@ #include #include +#include + #include "pointer_abstract_object.h" @@ -89,3 +91,70 @@ pointer_abstract_objectt::pointer_abstract_objectt(const constant_exprt &e): { assert(e.type().id()==ID_pointer); } + +/*******************************************************************\ + +Function: array_abstract_objectt::read_index + + Inputs: + env - the environment + index - the expression used to access the specific value in the array + + Outputs: An abstract object representing the value in the array + + Purpose: A helper function to read elements from an array. More precise + abstractions may override this to provide more precise results. + +\*******************************************************************/ + +abstract_object_pointert pointer_abstract_objectt::read_dereference( + const abstract_environmentt &env) const +{ + pointer_typet pointer_type(to_pointer_type(type)); + const typet &pointed_to_type=pointer_type.subtype(); + + return env.abstract_object_factory(pointed_to_type, true, false); +} + +/*******************************************************************\ + +Function: abstract_object_pointert array_abstract_objectt + + Inputs: + environment - the abstract environment + stack - the remaining stack of expressions on the LHS to evaluate + index_expr - the expression uses to access a specific index + value - the value we are trying to assign to that value in the array + merging_write - ? + + Outputs: The struct_abstract_objectt representing the result of writing + to a specific component. In this case this will always be top + as we are not tracking the value of this struct. + + Purpose: A helper function to evaluate writing to a component of a struct. + More precise abstractions may override this to + update what they are storing for a specific component. + +\*******************************************************************/ + +sharing_ptrt pointer_abstract_objectt::write_dereference( + abstract_environmentt &environment, + const std::stack stack, + const abstract_object_pointert value, + bool merging_write) +{ + if(is_top()) + { + environment.havoc("Writing to a 2value pointer"); + return sharing_ptrt( + new pointer_abstract_objectt(*this)); + } + else + { + sharing_ptrt copy( + new pointer_abstract_objectt(*this)); + copy->top=false; + copy->bottom=true; + return copy; + } +} diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index d8a8074d3c0..6218d0e0a29 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -8,10 +8,14 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_POINTER_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_POINTER_ABSTRACT_OBJECT_H + +#include + #include class typet; class constant_exprt; +class abstract_environmentt; class pointer_abstract_objectt:public abstract_objectt { @@ -23,6 +27,16 @@ class pointer_abstract_objectt:public abstract_objectt CLONE MERGE(abstract_objectt) + + // pointer interface + virtual abstract_object_pointert read_dereference( + const abstract_environmentt &env) const; + + virtual sharing_ptrt write_dereference( + abstract_environmentt &environment, + const std::stack stack, + const abstract_object_pointert value, + bool merging_write); }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_POINTER_ABSTRACT_OBJECT_H From 57c1e1bcf530785b376bc412501e55f6ab0e23cd Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Feb 2017 17:52:00 +0000 Subject: [PATCH 039/129] Moved the logic for resolving logical expressions into abstract_value This will allow for more precise abstractions to do better than a niave approach (where we can only resolve the expressions when we know exactly what they are). Use simplify expr to evaluate equals We simplify the two sides of it recursively then pass the whole expression (with constants replaced) to simplify_expr and see if we get a result back. --- .../abstract_enviroment.cpp | 73 ++++++------------- .../abstract_enviroment.h | 8 +- .../variable-sensitivity/abstract_object.cpp | 52 +++++++++++-- .../variable-sensitivity/abstract_object.h | 8 +- .../variable_sensitivity_domain.cpp | 6 +- 5 files changed, 84 insertions(+), 63 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index bb28ebb1e82..daf55559ee6 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -35,7 +35,7 @@ Function: abstract_environmentt::eval \*******************************************************************/ abstract_object_pointert abstract_environmentt::eval( - const exprt &expr) const + const exprt &expr, const namespacet &ns) const { assert(!is_bottom); typedef std::function eval_handlert; @@ -69,7 +69,7 @@ abstract_object_pointert abstract_environmentt::eval( member_exprt member_expr(to_member_expr(expr)); sharing_ptrt struct_abstract_object= std::dynamic_pointer_cast( - eval(member_expr.compound())); + eval(member_expr.compound(), ns)); return struct_abstract_object->read_component(*this, member_expr); } @@ -82,8 +82,7 @@ abstract_object_pointert abstract_environmentt::eval( #endif // TODO(tkiley): This needs special handling // For now just return top - return abstract_object_pointert( - new abstract_objectt(expr.type(), true, false)); + return abstract_object_factory(expr.type(), true, false); } }, { @@ -92,7 +91,7 @@ abstract_object_pointert abstract_environmentt::eval( dereference_exprt dereference(to_dereference_expr(expr)); sharing_ptrt pointer_abstract_object= std::dynamic_pointer_cast( - eval(dereference.pointer())); + eval(dereference.pointer(), ns)); return pointer_abstract_object->read_dereference(*this); } @@ -103,7 +102,7 @@ abstract_object_pointert abstract_environmentt::eval( index_exprt index_expr(to_index_expr(expr)); sharing_ptrt array_abstract_object= std::dynamic_pointer_cast( - eval(index_expr.array())); + eval(index_expr.array(), ns)); return array_abstract_object->read_index(*this, index_expr); } @@ -120,7 +119,16 @@ abstract_object_pointert abstract_environmentt::eval( const auto &handler=handlers.find(expr.id()); if(handler==handlers.cend()) { - return abstract_object_factory(expr.type(), true); + // No special handling required by the abstract environment + // delegate to the abstract object + if(expr.operands().size()==2) + { + return eval_binary_operations(expr, ns); + } + else + { + return abstract_object_factory(expr.type(), true); + } } else { @@ -267,9 +275,9 @@ Function: abstract_environmentt::assume \*******************************************************************/ -bool abstract_environmentt::assume(const exprt &expr) +bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) { - abstract_object_pointert res = eval(expr); + abstract_object_pointert res = eval(expr, ns); std::string not_implemented_string=__func__; not_implemented_string.append(" not implemented"); throw not_implemented_string; @@ -553,48 +561,13 @@ void abstract_environmentt::output( out << "}\n"; } -abstract_object_pointert abstract_environmentt::eval_logical( - const exprt &e) const +abstract_object_pointert abstract_environmentt::eval_binary_operations( + const exprt &e, const namespacet &ns) const { - typedef std::function eval_handlert; - std::map handlers= - { - { - ID_equal, [&](const exprt &expr) - { - abstract_object_pointert lhs=eval(expr.op0()); - abstract_object_pointert rhs=eval(expr.op1()); - - const exprt &lhs_value=lhs->to_constant(); - const exprt &rhs_value=rhs->to_constant(); - - if(lhs_value.id()==ID_nil || rhs_value.id()==ID_nil) - { - // One or both of the values is unknown so therefore we can't conclude - // whether this is true or false - return abstract_object_pointert( - new abstract_objectt(expr.type(), true, false)); - } - else - { - bool logical_result=lhs_value==rhs_value; - if(logical_result) - { - return abstract_object_pointert( - new constant_abstract_valuet(true_exprt())); - } - else - { - return abstract_object_pointert( - new constant_abstract_valuet(false_exprt())); - } - } - } - } - }; - - assert(handlers.find(e.id())!=handlers.end()); - return handlers[e.id()](e); + // Delegate responsibility of resolving to a boolean abstract object + // to the abstract object being compared against + abstract_object_pointert lhs=eval(e.op0(), ns); + return lhs->expression_transform_binary(e, *this, ns); } abstract_object_pointert abstract_environmentt::eval_rest(const exprt &e) const diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 4fb789b88c2..524f105865b 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -19,9 +19,10 @@ class abstract_environmentt { public: // These three are really the heart of the method - virtual abstract_object_pointert eval(const exprt &expr) const; + virtual abstract_object_pointert eval( + const exprt &expr, const namespacet &ns) const; virtual bool assign(const exprt &expr, const abstract_object_pointert value); - virtual bool assume(const exprt &expr); + virtual bool assume(const exprt &expr, const namespacet &ns); virtual abstract_object_pointert abstract_object_factory( const typet type, bool top=true, bool bottom=false) const; @@ -50,7 +51,8 @@ class abstract_environmentt bool is_bottom; // We may need to break out more of these cases into these - virtual abstract_object_pointert eval_logical(const exprt &e) const; + virtual abstract_object_pointert eval_binary_operations( + const exprt &e, const namespacet &ns) const; // Hook for domain specific handling of operators virtual abstract_object_pointert eval_rest(const exprt &e) const; diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index f905f0cc902..b31de93a968 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -6,10 +6,17 @@ \*******************************************************************/ -#include "abstract_object.h" #include + #include #include +#include +#include + +#include +#include + +#include "abstract_object.h" /*******************************************************************\ @@ -138,13 +145,48 @@ abstract_object_pointert abstract_objectt::merge( return m; } -#if 0 -abstract_object_pointert abstract_objectt::expression_transform_logical( - const exprt &expr, abstract_environmentt &environment) +abstract_object_pointert abstract_objectt::expression_transform_binary( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const { + assert(expr.operands().size()==2); + + abstract_object_pointert lhs_abstract_object=environment.eval(expr.op0(), ns); + abstract_object_pointert rhs_abstract_object=environment.eval(expr.op1(), ns); + const exprt &lhs_value=lhs_abstract_object->to_constant(); + const exprt &rhs_value=rhs_abstract_object->to_constant(); + + if(lhs_value.id()==ID_nil || rhs_value.id()==ID_nil) + { + // One or both of the values is unknown so therefore we can't conclude + // whether this is true or false + return abstract_object_pointert( + new abstract_objectt(expr.type(), true, false)); + } + else + { + exprt constant_replaced_expr=expr; + constant_replaced_expr.operands()[0]=lhs_value; + constant_replaced_expr.operands()[1]=rhs_value; + exprt simplified=simplify_expr(constant_replaced_expr, ns); + if(simplified.is_constant()) + { + constant_exprt constant_expr=to_constant_expr(simplified); + + // TODO(tkiley): This should be going through the abstract_object_factory + // but at the moment this produces a two value abstraction for type bool + // so for now we force it to be the constant abstraction + return abstract_object_pointert( + new constant_abstract_valuet(constant_expr)); + } + else + { + return environment.abstract_object_factory(expr.type(), true, false); + } + } } -#endif /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index c2d02574ca0..d12e11370a5 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -11,6 +11,7 @@ class typet; class constant_exprt; class abstract_environmentt; +class namespacet; #include #include @@ -80,12 +81,15 @@ class abstract_objectt const abstract_object_pointert op, bool &out_any_modifications); // Interface for transforms - //abstract_object_pointert expression_transform_logical(const exprt &expr, abstract_environmentt &environment); + abstract_object_pointert expression_transform_binary( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const; virtual exprt to_constant() const; virtual void output( - std::ostream &out, const class ai_baset &ai, const class namespacet &ns); + std::ostream &out, const class ai_baset &ai, const namespacet &ns); CLONE diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index ec261848dbe..dc67e9922be 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -66,7 +66,7 @@ void variable_sensitivity_domaint::transform( const code_assignt &inst = to_code_assign(instruction.code); // TODO : check return values - abstract_object_pointert r = abstract_state.eval(inst.rhs()); + abstract_object_pointert r = abstract_state.eval(inst.rhs(), ns); abstract_state.assign(inst.lhs(), r); } break; @@ -89,7 +89,7 @@ void variable_sensitivity_domaint::transform( break; case ASSUME: - abstract_state.assume(instruction.guard); + abstract_state.assume(instruction.guard, ns); break; case FUNCTION_CALL: @@ -256,7 +256,7 @@ bool variable_sensitivity_domaint::ai_simplify( return false; else { - sharing_ptrt res = abstract_state.eval(condition); + sharing_ptrt res = abstract_state.eval(condition, ns); exprt c = res->to_constant(); if (c.id() == ID_nil) From df286771e21e11b588742da69ec8ec015bdec238 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 24 Feb 2017 13:39:15 +0000 Subject: [PATCH 040/129] Fixed bug that would have occured for struct/pointer/array assigns --- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index daf55559ee6..047166e0848 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -250,14 +250,14 @@ bool abstract_environmentt::assign( } // Write the value for the root symbol back into the map - if (value->is_top()) + if (final_value->is_top()) { map.erase(symbol_expr); } else { - map[symbol_expr]=value; + map[symbol_expr]=final_value; } return true; } From 44b69ed3c34fade995c9f86c05395d8ac4e17f1e Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 24 Feb 2017 15:06:14 +0000 Subject: [PATCH 041/129] Removed the requirement on two operands Before we were only trying to resolve using the abstract objects things with two operands. There is no reason for this, we can try anything and if at any point we can't figure it out, we can always return top. All the logic is handled by simplify_expr anyway, we just recursively try to make sure all operands have been replaced with constants where possible. --- .../abstract_enviroment.cpp | 8 +- .../abstract_enviroment.h | 2 +- .../variable-sensitivity/abstract_object.cpp | 75 ++++++++++++------- .../variable-sensitivity/abstract_object.h | 2 +- 4 files changed, 52 insertions(+), 35 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 047166e0848..7aa374a28f8 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -121,9 +121,9 @@ abstract_object_pointert abstract_environmentt::eval( { // No special handling required by the abstract environment // delegate to the abstract object - if(expr.operands().size()==2) + if(expr.operands().size()>0) { - return eval_binary_operations(expr, ns); + return eval_expression(expr, ns); } else { @@ -561,13 +561,13 @@ void abstract_environmentt::output( out << "}\n"; } -abstract_object_pointert abstract_environmentt::eval_binary_operations( +abstract_object_pointert abstract_environmentt::eval_expression( const exprt &e, const namespacet &ns) const { // Delegate responsibility of resolving to a boolean abstract object // to the abstract object being compared against abstract_object_pointert lhs=eval(e.op0(), ns); - return lhs->expression_transform_binary(e, *this, ns); + return lhs->expression_transform(e, *this, ns); } abstract_object_pointert abstract_environmentt::eval_rest(const exprt &e) const diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 524f105865b..bc22cb91c8b 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -51,7 +51,7 @@ class abstract_environmentt bool is_bottom; // We may need to break out more of these cases into these - virtual abstract_object_pointert eval_binary_operations( + virtual abstract_object_pointert eval_expression( const exprt &e, const namespacet &ns) const; // Hook for domain specific handling of operators diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index b31de93a968..41c98db7abf 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -145,47 +145,64 @@ abstract_object_pointert abstract_objectt::merge( return m; } -abstract_object_pointert abstract_objectt::expression_transform_binary( +/*******************************************************************\ + +Function: abstract_objectt::expression_transform + + Inputs: + expr - the expression to evaluate and find the result of it. this will + be the symbol referred to be op0() + + Outputs: Returns the abstract_object representing the result of this expression + to the maximum precision available. + + Purpose: To try and resolve different expressions with the maximum level + of precision available. + +\*******************************************************************/ + +abstract_object_pointert abstract_objectt::expression_transform( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns) const { - assert(expr.operands().size()==2); - - abstract_object_pointert lhs_abstract_object=environment.eval(expr.op0(), ns); - abstract_object_pointert rhs_abstract_object=environment.eval(expr.op1(), ns); - - const exprt &lhs_value=lhs_abstract_object->to_constant(); - const exprt &rhs_value=rhs_abstract_object->to_constant(); - - if(lhs_value.id()==ID_nil || rhs_value.id()==ID_nil) - { - // One or both of the values is unknown so therefore we can't conclude - // whether this is true or false - return abstract_object_pointert( - new abstract_objectt(expr.type(), true, false)); - } - else + exprt constant_replaced_expr=expr; + constant_replaced_expr.operands().clear(); + for(const exprt &op : expr.operands()) { - exprt constant_replaced_expr=expr; - constant_replaced_expr.operands()[0]=lhs_value; - constant_replaced_expr.operands()[1]=rhs_value; - exprt simplified=simplify_expr(constant_replaced_expr, ns); - if(simplified.is_constant()) - { - constant_exprt constant_expr=to_constant_expr(simplified); + abstract_object_pointert lhs_abstract_object=environment.eval(op, ns); + const exprt &lhs_value=lhs_abstract_object->to_constant(); - // TODO(tkiley): This should be going through the abstract_object_factory - // but at the moment this produces a two value abstraction for type bool - // so for now we force it to be the constant abstraction + if(lhs_value.is_nil()) + { + // One of the values is true so we can't really do anything more with + // this expression and should just return top for the result return abstract_object_pointert( - new constant_abstract_valuet(constant_expr)); + new abstract_objectt(expr.type(), true, false)); } else { - return environment.abstract_object_factory(expr.type(), true, false); + // rebuild the operands list with constant versions of + // any symbols + constant_replaced_expr.operands().push_back(lhs_value); } } + + exprt simplified=simplify_expr(constant_replaced_expr, ns); + if(simplified.is_constant()) + { + constant_exprt constant_expr=to_constant_expr(simplified); + + // TODO(tkiley): This should be going through the abstract_object_factory + // but at the moment this produces a two value abstraction for type bool + // so for now we force it to be the constant abstraction + return abstract_object_pointert( + new constant_abstract_valuet(constant_expr)); + } + else + { + return environment.abstract_object_factory(expr.type(), true, false); + } } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index d12e11370a5..a185ebb1d8e 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -81,7 +81,7 @@ class abstract_objectt const abstract_object_pointert op, bool &out_any_modifications); // Interface for transforms - abstract_object_pointert expression_transform_binary( + abstract_object_pointert expression_transform( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns) const; From f2323f253a8a8d0718f5cbbeb7875497c9bc2435 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 24 Feb 2017 17:04:48 +0000 Subject: [PATCH 042/129] Simplify the expression before storing This deals with things like typecasts and additions so we don't set to top what we could otherwise handle --- .../abstract_enviroment.cpp | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 7aa374a28f8..f2aae1a9527 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef DEBUG @@ -108,31 +109,27 @@ abstract_object_pointert abstract_environmentt::eval( } } }; - #if 0 - [&](const exprt &expr) - { - return abstract_object_factory( - expr.type(), to_constant_expr(expr)); - } - } -#endif - const auto &handler=handlers.find(expr.id()); + + // first try to collapse constant folding + const exprt &simplified_expr=simplify_expr(expr, ns); + + const auto &handler=handlers.find(simplified_expr.id()); if(handler==handlers.cend()) { // No special handling required by the abstract environment // delegate to the abstract object - if(expr.operands().size()>0) + if(simplified_expr.operands().size()>0) { - return eval_expression(expr, ns); + return eval_expression(simplified_expr, ns); } else { - return abstract_object_factory(expr.type(), true); + return abstract_object_factory(simplified_expr.type(), true); } } else { - return handler->second(expr); + return handler->second(simplified_expr); } } @@ -317,7 +314,7 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( const typet type, bool top, bool bottom) const { // TODO (tkiley): Here we should look at some config file - if(type.id()==ID_signedbv) + if(type.id()==ID_signedbv || type.id()==ID_bool || type.id()==ID_c_bool) { return abstract_object_pointert( new constant_abstract_valuet(type, top, bottom)); @@ -347,7 +344,7 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( const typet type, const constant_exprt e) const { assert(type==e.type()); - if(type.id()==ID_signedbv) + if(type.id()==ID_signedbv || type.id()==ID_bool || type.id()==ID_c_bool) { return abstract_object_pointert( new constant_abstract_valuet(e)); From af2c1d35eee8ed6447aceb6ca9c7fdb4b80b649f Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 27 Feb 2017 16:48:19 +0000 Subject: [PATCH 043/129] Fixed issue where writing to a top value Before, since top values weren't in the map, the write would cause a crash as it would try and use a null pointer to call the relevant action (in the case of non-trivial types). --- .../variable-sensitivity/abstract_enviroment.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index f2aae1a9527..373876b6d30 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -238,7 +238,19 @@ bool abstract_environmentt::assign( // We added something to the stack that we couldn't deal with assert(handlers.find(next_expr.id())!=handlers.end()); - final_value=handlers[next_expr.id()](map[symbol_expr], stactions, value); + assert(value); + + // The symbol is not in the map - it is therefore top + abstract_object_pointert symbol_object; + if(map.find(symbol_expr)==map.end()) + { + symbol_object=abstract_object_factory(symbol_expr.type(), true, false); + } + else + { + symbol_object=map[symbol_expr]; + } + final_value=handlers[next_expr.id()](symbol_object, stactions, value); } else { From 0b8bff43025348856ef5a7dabc730e5629623dce Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 15:04:39 +0000 Subject: [PATCH 044/129] Add previously written design documentation to the relevant parts of the code. --- .../variable_sensitivity_domain.h | 54 +++++++++++ .../goto_analyzer_parse_options.h | 92 +++++++++++++++++++ 2 files changed, 146 insertions(+) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 8d6b89d0e06..b26ade5d644 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -4,6 +4,60 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com +There are different ways of handling arrays, structures, unions and +pointers. Our existing solution basically ignores them which is +imprecise at best and out-right wrong at worst. For one project we +needed to do better. We could have implemented a particular way of +handling them in an existing domain, created a new one with it, etc. +This would work but it means duplicate code and it is is inflexible when +the same person / the next person comes along and says "actually, we +really care about the pointer precision but less so the array so could +you just ...". Thus the idea was to do this properly: + +1. Build a "non-relational domain" and allow the abstractions used for +individual variables to be different. + +2. Give the user the option of which abstractions are used for structs, +unions, arrays and pointers. These are the sensitivity options +discussed above. + +3. Have the domain options control which kind of abstractions are used +for the individual values, i.e. constants, intervals, etc. + + +This is implemented in three parts: + +abstract_objectt : The base / interface for abstractions of a single +variable. The interface for these is effectively create (as top, +bottom, from a constant or copy), transform, merge, convert to constant +if possible. Child classes add additional bits of interface, for +example array abstractions need a "read element" and a "write element" +method, structures need a "read field" and "write field", etc. These +objects are intended to be immutable and thus operations tend to produce +pointers. This is so that we can easily produce copy-on-write maps of +them which we need for scaling and performance. There are also children +of these for the constant abstraction of one value, the interval +abstraction of one value (to be implemented), etc. + +abstract_environment : This contains the map from variable names for +abstract_objectt's (the "non-relational" part of the domain). The map +itself if copy-on-write for performance and scalability but this is all +wrapped up nicely in @danpoe's sharing_map. The interface here is +evaluate (exprt -> abstract_objectt*), assign (name, abstract_objectt* +-> bool), assume (exprt -> bool) and merge. It has a factory to build +abstract_objectt* from types or constants but apart from that, doesn't +know anything about which actual abstract_objectt's are being used. As +long as program variables that are arrays have an abstract_objectt which +has the array interface, and so on for structs, unions, etc. then the +abstractions used for values can be freely mixed and matched in any way +the user can get the factory to build. + +variable_sensitivity_domaint : Implements the ai_domain_baset interface +using an abstract_environment. The only real code here is the +'transform' method which looks at the instruction type and converts that +into calls to eval, assume, assign and merge. + + \*******************************************************************/ #ifndef CPROVER_GOTO_ANALYZER_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H #define CPROVER_GOTO_ANALYZER_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H diff --git a/src/goto-analyzer/goto_analyzer_parse_options.h b/src/goto-analyzer/goto_analyzer_parse_options.h index af2ca44af78..bbc64edf3ed 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.h +++ b/src/goto-analyzer/goto_analyzer_parse_options.h @@ -4,6 +4,98 @@ Module: Goto-Analyser Command Line Option Processing Author: Daniel Kroening, kroening@kroening.com +Goto-analyze is the tool front-end for CPROVER's classic style abstract +interpretation analyses. By "classic style" I mean, domains are C++ +objects, transformers are computed using C++ functions and the +fix-points are computed by iteration. This is in contrast to 2LS's +approach where everything is computed using quantifier-elimination. + +The analyses are mostly in analyses/ and although they are used in other +places in the code, the goal is that goto-analyze should eventually +provide an executable front-end for all of them. + +There are a lot of different analyses and a lot of ways they can be +used. Goto-analyze has five, largely independent, sets of options: + +1. Task : What you do once you've computed the domains. +2. Abstract interpreter : What kind of abstract interpretation you do. +3. Domain : What domain you use. +4. Sensitivity : How that domain handles things like arrays, pointers, etc. + (see variable_sensitivity_domain.h) +5. Output : What you do with the results. + +Formally speaking, 2, 3 and 4 are an artificial distinction as they are +all really parts of the "what domain" question. However they correspond +to parts of our code architecture, so ... they should stay. + +Ideally, the cross product of options should be supported but ... in +practice there will always be ones that are not meaningful. Those +should give errors. In addition there are some analyses which are +currently stand alone as they don't fit directly in to this model. For +example the unwind bounds analysis, which is both the task, the abstract +interpreter and the output. Where possible these should be integrated / +support the other options. In the case of the unwind analysis this +means the domain and it's sensitivity should be configurable. + + +Task +---- + +Tasks are implemented by the relevant file in goto-analyze/static_*. At +the moment they are each responsible for building the domain / using the +other options. As much as possible of this code should be shared. Some +of these inherit from messaget. They all probably should. + +Show : Prints out the domains for inspection or further use. + +Verify : Uses the domain to check all assertions in the code, marking +each one "SUCCESS" (the assertion always holds), "FAILURE if +reachable" (the assertion never holds), "UNKNOWN" (the assertion may or +may not hold). This is implemented using domain_simplify(). + +Simplify : Generates a new goto program with branch conditions, +assertions, assumptions and assignments simplified using the information +in the domain (again using domain_simplify()). This task is intended to +be used as a preprocessing step for other analysis. + +Invariants : (Not implemented yet) Use the domains to add assume() +statements to the code giving invariants generated from the domain. +These assumes don't reduce the space of possible executions; they make +existing invariants explicit. Again, intended as a preprocessing step. + + +Abstract Interpreter +-------------------- + +This option is effectively about how we compute the fix-point(s) / +which child class of ai_baset we use. I.E. ait or +concurrency_aware_ait, etc. For migrating / refactor / +unifying with the pointer analysis code we might want a +location_insensitive_ait or something but this is not urgent. +We will need a context_aware_ait, quite possibly the one +@danpoe has written elsewhere. + + +Domain +------ + +Which child of ai_domain_baset we use to represent the abstract state at +each location / implement the transformers. I expect most of these will +be non-relational (i.e. an abstract object for each variable) due to the +cost of implementing effective non-relational domains in this style vs. +using 2LS. The exception might be equalities, which we could implement +here. + + +Output +------ + +Text, XML, JSON plus some others for specific domains such as dependence +graphs in DOT format. + + + + \*******************************************************************/ /// \file From 4717f587ee261f068b98f88f5f3a459653f9cbfe Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 15:32:09 +0000 Subject: [PATCH 045/129] Improve the documentation of various methods. --- .../abstract_enviroment.cpp | 33 ++++++++++--------- .../variable_sensitivity_domain.cpp | 8 +++-- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 373876b6d30..ef4fb10640d 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -28,6 +28,7 @@ Function: abstract_environmentt::eval Inputs: expr - the expression to evaluate + ns - the current namespace Outputs: The abstract_object representing the value of the expression @@ -141,7 +142,7 @@ Function: abstract_environmentt::assign expr - the expression to assign to value - the value to assign to the expression - Outputs: ? + Outputs: A boolean, true if the assignment has changed the domain. Purpose: Assign a value to an expression @@ -276,11 +277,14 @@ bool abstract_environmentt::assign( Function: abstract_environmentt::assume Inputs: - expr - the expression inside the assume + expr - the expression that is to be assumed + ns - the current namespace - Outputs: ? + Outputs: True if the assume changed the domain. - Purpose: ? + Purpose: Reduces the domain to (an over-approximation) of the cases + when the the expression holds. Used to implement assume + statements and conditional branches. \*******************************************************************/ @@ -374,9 +378,9 @@ Function: abstract_environmentt::merge Inputs: env - the other environment - Outputs: ? + Outputs: A Boolean, true when the merge has changed something - Purpose: ? + Purpose: Computes the join between "this" and "b" \*******************************************************************/ @@ -454,7 +458,7 @@ Function: abstract_environmentt::havoc Inputs: havoc_string - debug string to track down havoc causing. - Outputs: + Outputs: None Purpose: Set the domain to top @@ -470,9 +474,9 @@ void abstract_environmentt::havoc(const std::string &havoc_string) Function: abstract_environmentt::make_top - Inputs: + Inputs: None - Outputs: + Outputs: None Purpose: Set the domain to top @@ -481,7 +485,6 @@ Function: abstract_environmentt::make_top void abstract_environmentt::make_top() { // since we assume anything is not in the map is top this is sufficient - // TODO: need a flag for bottom map.clear(); is_bottom=false; } @@ -490,9 +493,9 @@ void abstract_environmentt::make_top() Function: abstract_environmentt::make_bottom - Inputs: + Inputs: None - Outputs: + Outputs: None Purpose: Set the domain to top @@ -544,10 +547,10 @@ Function: abstract_environmentt::output Inputs: out - the stream to write to - ai - ? - ns - ? + ai - the abstract interpreter that contains this domain + ns - the current namespace - Outputs: + Outputs: None Purpose: Print out all the values in the abstract object map diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index dc67e9922be..0a274463cdf 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -105,6 +105,8 @@ void variable_sensitivity_domaint::transform( case ASSERT: // Conditions on the program, do not alter the data or information // flow and thus can be ignored. + // Checking of assertions can only be reasonably done once the fix-point + // has been computed, i.e. after all of the calls to transform. break; case SKIP: @@ -238,14 +240,16 @@ bool variable_sensitivity_domaint::merge( Function: variable_sensitivity_domaint::ai_simplify Inputs: - condition - the expression to evaluate to true or false + condition - the expression to simplify ns - the namespace lhs - is the expression on the left hand side Outputs: True if simplified the condition. False otherwise. condition will be updated with the simplified condition if it has worked - Purpose: To resolve a condition down to a possibly known boolean value + Purpose: Use the information in the domain to simplify the expression + with respect to the current location. This may be able to + reduce some values to constants. \*******************************************************************/ From 61759965a530e19dea6271eccc6ad575ba9a1ba5 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 15:56:34 +0000 Subject: [PATCH 046/129] Give a generic implementation of assume. --- .../abstract_enviroment.cpp | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index ef4fb10640d..fd30ea4a51e 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -290,24 +290,30 @@ Function: abstract_environmentt::assume bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) { + // We should only attempt to assume Boolean things + // This should be enforced by the well-structured-ness of the goto-program + assert(expr.type().id()==ID_bool); + + // Evaluate the expression abstract_object_pointert res = eval(expr, ns); - std::string not_implemented_string=__func__; - not_implemented_string.append(" not implemented"); - throw not_implemented_string; - // Need abstract_booleant -#if 0 - abstract_booleant *b = dynamic_cast(res); - assert(b != NULL); + exprt possibly_constant = res->to_constant(); - if (b->to_constant().is_false()) + if (possibly_constant.id()!=ID_nil) // I.E. actually a value { - make_bottom(); - return true; + assert(possibly_constant.type().id()==ID_bool); // Should be of the right type + + if (possibly_constant.is_false()) + { + bool currently_bottom = get_is_bottom(); + make_bottom(); + return !currently_bottom; + } } - else - return false; -#endif + + // TODO - need a way of converting x==23 into an assign for the value of x + + return false; } From 4a294f36a3eae6ab26fc1861643dbc4725e93cff Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 15:59:59 +0000 Subject: [PATCH 047/129] Enable the use of assume for branches. --- .../variable-sensitivity/variable_sensitivity_domain.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 0a274463cdf..7736eef675d 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -74,17 +74,15 @@ void variable_sensitivity_domaint::transform( case GOTO: { // TODO(tkiley): add support for flow sensitivity -#if 0 - if (flow_sensitivity == FLOW_SENSITIVE) + if (1) // (flow_sensitivity == FLOW_SENSITIVE) { locationt next=from; next++; if(next==to) - assume(not_exprt(instruction.guard)); + abstract_state.assume(not_exprt(instruction.guard), ns); else - assume(instruction.guard); + abstract_state.assume(instruction.guard, ns); } -#endif } break; From 12f8d7e0e8f5fd2235423add8553ff6ab3337c88 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 27 Feb 2017 16:54:13 +0000 Subject: [PATCH 048/129] Basic implementation of the sensitive pointer Created class that tracks an abstract object that it is pointing to. Involved modifying constructors to take exprt rather than constant_exprt since would want to create the pointer using an address_of_exprt which isn't a constant_exprt. I'm not sure if this is a good change but couldn't think of an alternative. --- src/analyses/Makefile | 1 + .../abstract_enviroment.cpp | 27 +- .../abstract_enviroment.h | 2 +- .../variable-sensitivity/abstract_object.cpp | 2 +- .../variable-sensitivity/abstract_object.h | 2 +- .../variable-sensitivity/abstract_value.cpp | 2 +- .../variable-sensitivity/abstract_value.h | 2 +- .../constant_abstract_value.cpp | 2 +- .../constant_abstract_value.h | 2 +- .../constant_pointer_abstract_object.cpp | 298 ++++++++++++++++++ .../constant_pointer_abstract_object.h | 56 ++++ .../pointer_abstract_object.cpp | 4 +- .../pointer_abstract_object.h | 2 +- 13 files changed, 384 insertions(+), 18 deletions(-) create mode 100644 src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/constant_pointer_abstract_object.h diff --git a/src/analyses/Makefile b/src/analyses/Makefile index 14fc6bdadcd..2ed092359d7 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -29,6 +29,7 @@ SRC = ai.cpp \ variable-sensitivity/abstract_value.cpp \ variable-sensitivity/array_abstract_object.cpp \ variable-sensitivity/constant_abstract_value.cpp \ + variable-sensitivity/constant_pointer_abstract_object.cpp \ variable-sensitivity/pointer_abstract_object.cpp \ variable-sensitivity/struct_abstract_object.cpp \ variable-sensitivity/variable_sensitivity_domain.cpp \ diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index fd30ea4a51e..2fda2630408 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -62,7 +63,7 @@ abstract_object_pointert abstract_environmentt::eval( ID_constant, [&](const exprt &expr) { return abstract_object_factory( - expr.type(), to_constant_expr(expr)); + expr.type(), to_constant_expr(expr), ns); } }, { @@ -79,12 +80,12 @@ abstract_object_pointert abstract_environmentt::eval( { ID_address_of, [&](const exprt &expr) { -#if 0 - address_of_exprt address_expr(to_address_of_expr(expr)); -#endif - // TODO(tkiley): This needs special handling - // For now just return top - return abstract_object_factory(expr.type(), true, false); + sharing_ptrt pointer_object= + std::dynamic_pointer_cast( + abstract_object_factory(expr.type(), expr, ns)); + + // Store the abstract object in the pointer + return pointer_object; } }, { @@ -341,6 +342,11 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( return abstract_object_pointert( new constant_abstract_valuet(type, top, bottom)); } + else if(type.id()==ID_pointer) + { + return abstract_object_pointert( + new constant_pointer_abstract_objectt(type, top, bottom, *this)); + } else { return abstract_object_pointert(new abstract_objectt(type, top, false)); @@ -363,7 +369,7 @@ Function: abstract_environmentt::abstract_object_factory \*******************************************************************/ abstract_object_pointert abstract_environmentt::abstract_object_factory( - const typet type, const constant_exprt e) const + const typet type, const exprt e, const namespacet &ns) const { assert(type==e.type()); if(type.id()==ID_signedbv || type.id()==ID_bool || type.id()==ID_c_bool) @@ -371,6 +377,11 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( return abstract_object_pointert( new constant_abstract_valuet(e)); } + else if(type.id()==ID_pointer) + { + return abstract_object_pointert( + new constant_pointer_abstract_objectt(e, *this, ns)); + } else { return abstract_object_pointert(new abstract_objectt(e)); diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index bc22cb91c8b..17c1f564e3c 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -29,7 +29,7 @@ class abstract_environmentt // For converting constants in the program // Maybe these two should be compacted to one call... virtual abstract_object_pointert abstract_object_factory( - const typet type, const constant_exprt e) const; + const typet type, const exprt e, const namespacet &ns) const; virtual bool merge(const abstract_environmentt &env); diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 41c98db7abf..1e836632ce3 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -87,7 +87,7 @@ Function: abstract_objectt::abstract_objectt \*******************************************************************/ -abstract_objectt::abstract_objectt(const constant_exprt &expr): +abstract_objectt::abstract_objectt(const exprt &expr): type(expr.type()), top(true), bottom(false) {} diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index a185ebb1d8e..e6668ad5064 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -65,7 +65,7 @@ class abstract_objectt abstract_objectt(const typet &type); abstract_objectt(const typet &type, bool top, bool bottom); abstract_objectt(const abstract_objectt &old); - abstract_objectt(const constant_exprt &expr); + abstract_objectt(const exprt &expr); const typet &get_type() const; virtual bool is_top() const; diff --git a/src/analyses/variable-sensitivity/abstract_value.cpp b/src/analyses/variable-sensitivity/abstract_value.cpp index 4565a76ea47..3f188de0851 100644 --- a/src/analyses/variable-sensitivity/abstract_value.cpp +++ b/src/analyses/variable-sensitivity/abstract_value.cpp @@ -67,6 +67,6 @@ abstract_valuet::abstract_valuet(const abstract_valuet &old): abstract_objectt(old) {} -abstract_valuet::abstract_valuet(const constant_exprt &expr): +abstract_valuet::abstract_valuet(const exprt &expr): abstract_objectt(expr) {} diff --git a/src/analyses/variable-sensitivity/abstract_value.h b/src/analyses/variable-sensitivity/abstract_value.h index 3fa255933d8..0dda25f2b38 100644 --- a/src/analyses/variable-sensitivity/abstract_value.h +++ b/src/analyses/variable-sensitivity/abstract_value.h @@ -17,7 +17,7 @@ class abstract_valuet:public abstract_objectt abstract_valuet(const typet &type); abstract_valuet(const typet &type, bool top, bool bottom); abstract_valuet(const abstract_valuet &old); - abstract_valuet(const constant_exprt &expr); + abstract_valuet(const exprt &expr); CLONE MERGE(abstract_objectt) diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index 2b855fad2f0..011c4749df7 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -22,7 +22,7 @@ constant_abstract_valuet::constant_abstract_valuet( abstract_valuet(old), value(old.value) {} -constant_abstract_valuet::constant_abstract_valuet(const constant_exprt e): +constant_abstract_valuet::constant_abstract_valuet(const exprt e): abstract_valuet(e), value(e) { top=false; diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 0f17cb325fd..410e41cf7e8 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -21,7 +21,7 @@ class constant_abstract_valuet : public abstract_valuet constant_abstract_valuet(typet t); constant_abstract_valuet(typet t, bool tp, bool bttm); constant_abstract_valuet(const constant_abstract_valuet &old); - constant_abstract_valuet(const constant_exprt e); + constant_abstract_valuet(const exprt e); CLONE MERGE(abstract_valuet) diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp new file mode 100644 index 00000000000..68a777c982b --- /dev/null +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -0,0 +1,298 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ + + +#include +#include +#include +#include "constant_pointer_abstract_object.h" + +/*******************************************************************\ + +Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt + + Inputs: + type - the type the abstract_object is representing + + Outputs: + + Purpose: + +\*******************************************************************/ + +constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( + const typet &t, const abstract_environmentt &enviroment): + pointer_abstract_objectt(t) +{ + assert(t.id()==ID_pointer); + value=enviroment.abstract_object_factory(t.subtype(), true, false); +} + +/*******************************************************************\ + +Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt + + Inputs: + type - the type the abstract_object is representing + top - is the abstract_object starting as top + bottom - is the abstract_object starting as bottom + + Outputs: + + Purpose: Start the abstract object at either top or bottom or neither + Asserts if both top and bottom are true + +\*******************************************************************/ + +constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( + const typet &t, bool tp, bool bttm, const abstract_environmentt &enviroment): + pointer_abstract_objectt(t, tp, bttm) +{ + assert(t.id()==ID_pointer); + value=enviroment.abstract_object_factory(t.subtype(), top, bottom); +} + +/*******************************************************************\ + +Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt + + Inputs: + old - the abstract object to copy from + + Outputs: + + Purpose: + +\*******************************************************************/ + +constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( + const constant_pointer_abstract_objectt &old): + pointer_abstract_objectt(old), value(old.value) +{} + +/*******************************************************************\ + +Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt + + Inputs: + expr - the expression to use as the starting pointer for an abstract object + + Outputs: + + Purpose: + +\*******************************************************************/ + +constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( + const exprt &e, + const abstract_environmentt &enviroment, + const namespacet &ns): + pointer_abstract_objectt(e) +{ + assert(e.type().id()==ID_pointer); + + // TODO(tkiley): Should here really be handling the different ways we + // can create a pointer + if(e.id()==ID_address_of) + { + address_of_exprt address_expr(to_address_of_expr(e)); + value=enviroment.eval(address_expr.object(), ns); + top=false; + } + else + { + if(e.id()==ID_constant) + { + constant_exprt constant_expr(to_constant_expr(e)); + if(constant_expr.get_value()==ID_NULL) + { + value=nullptr; + top=false; + } + else + { + // TODO(tkiley): These should probably be logged. + // unknown type + value=enviroment.abstract_object_factory(type.subtype(), true, false); + } + } + else + { + value=enviroment.abstract_object_factory(type.subtype(), true, false); + } + } +} + +/*******************************************************************\ + +Function: constant_pointer_abstract_objectt::to_constant + + Inputs: + + Outputs: Returns an expression representing the value if it can. + Returns a nil expression if it can be more than one value. + Returns null_pointer expression if it must be null + Returns an address_of_exprt with the value set to the + result of to_constant called on whatever abstract object this + pointer is pointing to. + + Purpose: To try and find a constant expression for this abstract object + +\*******************************************************************/ + +exprt constant_pointer_abstract_objectt::to_constant() const +{ + if(top || bottom) + { + return pointer_abstract_objectt::to_constant(); + } + else + { + if(value==nullptr) + { + return null_pointer_exprt(to_pointer_type(type)); + } + else + { + const exprt &value_expr=value->to_constant(); + address_of_exprt address_expr(value_expr); + return address_expr; + } + } +} + +/*******************************************************************\ + +Function: constant_pointer_abstract_objectt::output + + Inputs: + out - the stream to write to + ai - ? + ns - ? + + Outputs: + + Purpose: Print the value of the pointer. Either NULL if nullpointer or + ptr -> ( output of what the pointer is pointing to). + +\*******************************************************************/ + +void constant_pointer_abstract_objectt::output( + std::ostream &out, const ai_baset &ai, const namespacet &ns) +{ + if(top || bottom) + { + pointer_abstract_objectt::output(out, ai, ns); + } + else + { + if(value==nullptr) + { + out << "NULL"; + } + else + { + out << "ptr ->("; + value->output(out, ai, ns); + out << ")"; + } + } +} + +/*******************************************************************\ + +Function: constant_pointer_abstract_objectt::read_dereference + + Inputs: + env - the environment + + Outputs: An abstract object representing the value this pointer is pointing + to + + Purpose: A helper function to dereference a value from a pointer. Providing + the pointer can only be pointing at one thing, returns an abstract + object representing that thing. If null or top will return top. + +\*******************************************************************/ + +abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( + const abstract_environmentt &env) const +{ + if(top || bottom || value==nullptr) + { + // Return top if dereferencing a null pointer or we are top + bool is_value_top = top || value==nullptr; + return env.abstract_object_factory( + type.subtype(), is_value_top, !is_value_top); + } + else + { + return value; + } +} + +/*******************************************************************\ + +Function: constant_pointer_abstract_objectt::write_dereference + + Inputs: + environment - the environment + stack - the remaining stack + new_value - the value to write to the dereferenced pointer + merging_write - is it a merging write (i.e. we aren't certain + we are writing to this particular pointer therefore + the value should be merged with whatever is already there + or we are certain we are writing to this pointer so + therefore the value can be replaced + + Outputs: A modified abstract object representing this pointer after it + has been written to. + + Purpose: A helper function to evaluate writing to a pointers value. + If the pointer can only be pointing to one element that it overwrites + that element (or merges if merging_write) with the new value. + If don't know what we are pointing to, we delegate to the parent. + +\*******************************************************************/ + +sharing_ptrt + constant_pointer_abstract_objectt::write_dereference( + abstract_environmentt &environment, + const std::stack stack, + const abstract_object_pointert new_value, + bool merging_write) +{ + if(top || bottom) + { + return pointer_abstract_objectt::write_dereference( + environment, stack, new_value, merging_write); + } + else + { + // TODO(tkiley): support the stack + assert(stack.empty()); + + sharing_ptrt copy= + sharing_ptrt( + new constant_pointer_abstract_objectt(*this)); + + // for + // environment.assign() + + if(merging_write) + { + bool modifications; + copy->value=value->merge(new_value, modifications); + } + else + { + copy->value=new_value; + } + return copy; + } +} diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h new file mode 100644 index 00000000000..ef2cba712c1 --- /dev/null +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -0,0 +1,56 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_POINTER_ABSTRACT_OBJECT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_POINTER_ABSTRACT_OBJECT_H + +#include + +class constant_pointer_abstract_objectt:public pointer_abstract_objectt +{ +private: + typedef sharing_ptrt + constant_pointer_abstract_pointert; +public: + constant_pointer_abstract_objectt( + const typet &type, const abstract_environmentt &enviroment); + + constant_pointer_abstract_objectt( + const typet &type, + bool top, + bool bottom, const abstract_environmentt &enviroment); + + constant_pointer_abstract_objectt( + const constant_pointer_abstract_objectt &old); + + constant_pointer_abstract_objectt( + const exprt &expr, + const abstract_environmentt &enviroment, + const namespacet &ns); + + CLONE + MERGE(pointer_abstract_objectt) + + exprt to_constant() const; + void output(std::ostream &out, const ai_baset &ai, const namespacet &ns); + + abstract_object_pointert read_dereference( + const abstract_environmentt &env) const; + + sharing_ptrt write_dereference( + abstract_environmentt &environment, + const std::stack stack, + const abstract_object_pointert value, + bool merging_write); + +private: + abstract_object_pointert value; + + +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_POINTER_ABSTRACT_OBJECT_H // NOLINT(*) diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index 49c221d349a..e6c7c1e1b42 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -86,8 +86,8 @@ Function: pointer_abstract_objectt::pointer_abstract_objectt \*******************************************************************/ -pointer_abstract_objectt::pointer_abstract_objectt(const constant_exprt &e): - abstract_objectt(e) +pointer_abstract_objectt::pointer_abstract_objectt(const exprt &e): + abstract_objectt(e) { assert(e.type().id()==ID_pointer); } diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index 6218d0e0a29..8c4fa17e6b6 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -23,7 +23,7 @@ class pointer_abstract_objectt:public abstract_objectt explicit pointer_abstract_objectt(const typet &type); pointer_abstract_objectt(const typet &type, bool top, bool bottom); explicit pointer_abstract_objectt(const pointer_abstract_objectt &old); - explicit pointer_abstract_objectt(const constant_exprt &expr); + explicit pointer_abstract_objectt(const exprt &e); CLONE MERGE(abstract_objectt) From 84717856a9dfcc7f118503e5f4fe6c4becf2fb39 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 27 Feb 2017 17:02:37 +0000 Subject: [PATCH 049/129] Fixing comments in pointer_abstract_object --- .../pointer_abstract_object.cpp | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index e6c7c1e1b42..3012cea5bc0 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -94,13 +94,12 @@ pointer_abstract_objectt::pointer_abstract_objectt(const exprt &e): /*******************************************************************\ -Function: array_abstract_objectt::read_index +Function: pointer_abstract_objectt::read_dereference Inputs: env - the environment - index - the expression used to access the specific value in the array - Outputs: An abstract object representing the value in the array + Outputs: An abstract object representing the value being pointed to Purpose: A helper function to read elements from an array. More precise abstractions may override this to provide more precise results. @@ -118,30 +117,33 @@ abstract_object_pointert pointer_abstract_objectt::read_dereference( /*******************************************************************\ -Function: abstract_object_pointert array_abstract_objectt +Function: pointer_abstract_objectt::write_dereference Inputs: environment - the abstract environment stack - the remaining stack of expressions on the LHS to evaluate - index_expr - the expression uses to access a specific index - value - the value we are trying to assign to that value in the array - merging_write - ? + value - the value we are trying to assign to what the pointer is + pointing to + merging_write - is it a merging write (i.e. we aren't certain + we are writing to this particular pointer therefore + the value should be merged with whatever is already there + or we are certain we are writing to this pointer so + therefore the value can be replaced - Outputs: The struct_abstract_objectt representing the result of writing - to a specific component. In this case this will always be top - as we are not tracking the value of this struct. + Outputs: A modified abstract object representing this pointer after it + has been written to. - Purpose: A helper function to evaluate writing to a component of a struct. - More precise abstractions may override this to - update what they are storing for a specific component. + Purpose: A helper function to evaluate writing to a pointers value. More + precise abstractions may override this provide more precise results. \*******************************************************************/ -sharing_ptrt pointer_abstract_objectt::write_dereference( - abstract_environmentt &environment, - const std::stack stack, - const abstract_object_pointert value, - bool merging_write) +sharing_ptrt + pointer_abstract_objectt::write_dereference( + abstract_environmentt &environment, + const std::stack stack, + const abstract_object_pointert value, + bool merging_write) { if(is_top()) { From de8af33c6a0982104586a3b912d05ab42eb846be Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 10:57:45 +0000 Subject: [PATCH 050/129] Adding merge state --- .../constant_pointer_abstract_object.cpp | 42 +++++++++++++++++++ .../constant_pointer_abstract_object.h | 4 ++ 2 files changed, 46 insertions(+) diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 68a777c982b..c3cd140a0aa 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -130,6 +130,48 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( /*******************************************************************\ +Function: constant_pointer_abstract_objectt::merge_state + + Inputs: + op1 - the first pointer abstract object + op2 - the second pointer abstract object + + Outputs: Returns true if this changed from op1 + + Purpose: Set this abstract object to be the result of merging two + other abstract objects. This handles the case where if they are + both pointing to the same object we keep the value. + +\*******************************************************************/ + +bool constant_pointer_abstract_objectt::merge_state( + const constant_pointer_abstract_pointert op1, + const constant_pointer_abstract_pointert op2) +{ + bool parent_merge_change=abstract_objectt::merge_state(op1, op2); + if(top || bottom) + { + return parent_merge_change; + } + else + { + if(op1->value==op2->value) + { + value=op1->value; + return false; + } + else + { + top=true; + value=nullptr; + assert(!bottom); + return !op1->top; + } + } +} + +/*******************************************************************\ + Function: constant_pointer_abstract_objectt::to_constant Inputs: diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index ef2cba712c1..3b156fd665a 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -35,6 +35,10 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt CLONE MERGE(pointer_abstract_objectt) + bool merge_state( + const constant_pointer_abstract_pointert op1, + const constant_pointer_abstract_pointert op2); + exprt to_constant() const; void output(std::ostream &out, const ai_baset &ai, const namespacet &ns); From 28b0139597156fd70ede15f718cafce8fc0d21e3 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 13:42:04 +0000 Subject: [PATCH 051/129] Supporting stack when writing Use a ping-pong between the abstract enviroments and the abstract objects to resolve the stack --- .../abstract_enviroment.cpp | 187 +++++++++++------- .../abstract_enviroment.h | 8 + .../constant_pointer_abstract_object.cpp | 32 +-- .../struct_abstract_object.cpp | 3 +- .../struct_abstract_object.h | 2 +- 5 files changed, 146 insertions(+), 86 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 2fda2630408..31d10d77e58 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -152,9 +152,12 @@ Function: abstract_environmentt::assign bool abstract_environmentt::assign( const exprt &expr, const abstract_object_pointert value) { + assert(value); + + // Build a stack of index, member and dereference accesses which + // we will work through the relevant abstract objects exprt s = expr; std::stack stactions; // I'm not a continuation, honest guv' - while (s.id() != ID_symbol) { if (s.id() == ID_index || s.id() == ID_member || s.id() == ID_dereference) @@ -172,76 +175,12 @@ bool abstract_environmentt::assign( const symbol_exprt &symbol_expr(to_symbol_expr(s)); + // This is the root abstract object that is in the map of abstract objects + // It might not have the same type as value if the above stack isn't empty abstract_object_pointert final_value; if(!stactions.empty()) { - const exprt & next_expr=stactions.top(); - stactions.pop(); - - typedef std::function< - abstract_object_pointert( - abstract_object_pointert, // The symbol we are modifying - std::stack, // The remaining stack - abstract_object_pointert)> // The value we are writing. - stacion_functiont; - - // Each handler takes the abstract object referenced, copies it, - // writes according to the type of expression (e.g. for ID_member) - // we would (should!) have an abstract_struct_objectt which has a - // write_member which will attempt to update the abstract object for the - // relevant member. This modified abstract object is returned and this - // is inserted back into the map - std::map handlers= - { - { - ID_index, [&]( - const abstract_object_pointert lhs_object, - std::stack stack, - abstract_object_pointert rhs_object) - { - sharing_ptrt array_abstract_object= - std::dynamic_pointer_cast(lhs_object); - sharing_ptrt modified_array= - array_abstract_object->write_index( - *this, stactions, to_index_expr(next_expr), rhs_object, false); - return modified_array; - } - }, - { - ID_member, [&]( - const abstract_object_pointert lhs_object, - std::stack stack, - abstract_object_pointert rhs_object) - { - sharing_ptrt struct_abstract_object= - std::dynamic_pointer_cast(lhs_object); - sharing_ptrt modified_struct= - struct_abstract_object->write_component( - *this, stactions, to_member_expr(next_expr), rhs_object); - return modified_struct; - } - }, - { - ID_dereference, [&]( - const abstract_object_pointert lhs_object, - std::stack stack, - abstract_object_pointert rhs_object) - { - sharing_ptrt pointer_abstract_object= - std::dynamic_pointer_cast(lhs_object); - sharing_ptrt modified_pointer= - pointer_abstract_object->write_dereference( - *this, stactions, rhs_object, false); - return modified_pointer; - } - } - }; - - // We added something to the stack that we couldn't deal with - assert(handlers.find(next_expr.id())!=handlers.end()); - assert(value); - // The symbol is not in the map - it is therefore top abstract_object_pointert symbol_object; if(map.find(symbol_expr)==map.end()) @@ -252,7 +191,7 @@ bool abstract_environmentt::assign( { symbol_object=map[symbol_expr]; } - final_value=handlers[next_expr.id()](symbol_object, stactions, value); + final_value=write(symbol_object, value, stactions, false); } else { @@ -264,7 +203,6 @@ bool abstract_environmentt::assign( if (final_value->is_top()) { map.erase(symbol_expr); - } else { @@ -275,6 +213,117 @@ bool abstract_environmentt::assign( /*******************************************************************\ +Function: abstract_object_pointert abstract_environmentt::write + + Inputs: + lhs - the abstract object for the left hand side of the write (i.e. the one + to update). + rhs - the value we are trying to write to the left hand side + remaining_stack - what is left of the stack before the rhs can replace or be + merged with the rhs + merge_write - Are re replacing the left hand side with the right hand side + (e.g. we know for a fact that we are overwriting this object) + or could the write in fact not take place and therefore we + should merge to model the case where it did not. + + Outputs: A modified version of the rhs after the write has taken place + + Purpose: Write an abstract object onto another respecting a stack of + member, index and dereference access. This ping-pongs between + this method and the relevant write methods in abstract_struct, + abstract_pointer and abstract_array until the stack is empty + +\*******************************************************************/ +abstract_object_pointert abstract_environmentt::write( + abstract_object_pointert lhs, + abstract_object_pointert rhs, + std::stack remaining_stack, + bool merge_write) +{ + assert(!remaining_stack.empty()); + const exprt & next_expr=remaining_stack.top(); + remaining_stack.pop(); + + typedef std::function< + abstract_object_pointert( + abstract_object_pointert, // The symbol we are modifying + std::stack, // The remaining stack + abstract_object_pointert)> // The value we are writing. + stacion_functiont; + + // Each handler takes the abstract object referenced, copies it, + // writes according to the type of expression (e.g. for ID_member) + // we would (should!) have an abstract_struct_objectt which has a + // write_member which will attempt to update the abstract object for the + // relevant member. This modified abstract object is returned and this + // is inserted back into the map + std::map handlers= + { + { + ID_index, [&]( + const abstract_object_pointert lhs_object, + std::stack stack, + abstract_object_pointert rhs_object) + { + sharing_ptrt array_abstract_object= + std::dynamic_pointer_cast(lhs_object); + + sharing_ptrt modified_array= + array_abstract_object->write_index( + *this, + stack, + to_index_expr(next_expr), + rhs_object, + merge_write); + + return modified_array; + } + }, + { + ID_member, [&]( + const abstract_object_pointert lhs_object, + std::stack stack, + abstract_object_pointert rhs_object) + { + sharing_ptrt struct_abstract_object= + std::dynamic_pointer_cast(lhs_object); + + sharing_ptrt modified_struct= + struct_abstract_object->write_component( + *this, + stack, + to_member_expr(next_expr), + rhs_object, + merge_write); + + return modified_struct; + } + }, + { + ID_dereference, [&]( + const abstract_object_pointert lhs_object, + std::stack stack, + abstract_object_pointert rhs_object) + { + sharing_ptrt pointer_abstract_object= + std::dynamic_pointer_cast(lhs_object); + + sharing_ptrt modified_pointer= + pointer_abstract_object->write_dereference( + *this, stack, rhs_object, merge_write); + + return modified_pointer; + } + } + }; + + // We added something to the stack that we couldn't deal with + assert(handlers.find(next_expr.id())!=handlers.end()); + return handlers[next_expr.id()](lhs, remaining_stack, rhs); +} + +/*******************************************************************\ + Function: abstract_environmentt::assume Inputs: diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 17c1f564e3c..f7b9597410b 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -24,6 +25,11 @@ class abstract_environmentt virtual bool assign(const exprt &expr, const abstract_object_pointert value); virtual bool assume(const exprt &expr, const namespacet &ns); + virtual abstract_object_pointert write(abstract_object_pointert lhs, + abstract_object_pointert rhs, + std::stack remaining_stack, + bool merge_write); + virtual abstract_object_pointert abstract_object_factory( const typet type, bool top=true, bool bottom=false) const; // For converting constants in the program @@ -57,6 +63,8 @@ class abstract_environmentt // Hook for domain specific handling of operators virtual abstract_object_pointert eval_rest(const exprt &e) const; + + typedef symbol_exprt map_keyt; std::map map; diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index c3cd140a0aa..58c738a5c29 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -316,25 +316,27 @@ sharing_ptrt } else { - // TODO(tkiley): support the stack - assert(stack.empty()); - - sharing_ptrt copy= - sharing_ptrt( - new constant_pointer_abstract_objectt(*this)); - - // for - // environment.assign() - - if(merging_write) + if(stack.empty()) { - bool modifications; - copy->value=value->merge(new_value, modifications); + sharing_ptrt copy= + sharing_ptrt( + new constant_pointer_abstract_objectt(*this)); + + if(merging_write) + { + bool modifications; + copy->value=value->merge(new_value, modifications); + } + else + { + copy->value=new_value; + } + return copy; } else { - copy->value=new_value; + return std::dynamic_pointer_cast( + environment.write(value, new_value, stack, merging_write)); } - return copy; } } diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index 1e2031a36dc..83a0e966e28 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -143,7 +143,8 @@ sharing_ptrt struct_abstract_objectt::write_component( const abstract_environmentt &environment, const std::stack stack, const member_exprt &member_expr, - const abstract_object_pointert value) + const abstract_object_pointert value, + bool merging_write) { if(is_top()) { diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index aacb0c26e4b..16a02ca9d0a 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -34,7 +34,7 @@ class struct_abstract_objectt:public abstract_objectt const abstract_environmentt &environment, const std::stack stack, const member_exprt &member_expr, - const abstract_object_pointert value); + const abstract_object_pointert value, bool merging_write); }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H From 92698fcd8cc779fb847c2d7dd4b301aad83f78c6 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 14:18:35 +0000 Subject: [PATCH 052/129] Changed the pointer abstract object to store an expression Before there was a problem where if we stored an abstract object that get modified, as this would cause a copy, the pointer would point at the old value. To resolve, just store an expression representing what it is pointing to. This can then be re-evaluated by the enviroment to find its current possible values. --- .../abstract_enviroment.cpp | 12 ++- .../abstract_enviroment.h | 15 ++-- .../constant_pointer_abstract_object.cpp | 78 ++++++++++++------- .../constant_pointer_abstract_object.h | 5 +- .../pointer_abstract_object.cpp | 5 +- .../pointer_abstract_object.h | 3 +- .../variable_sensitivity_domain.cpp | 5 +- 7 files changed, 80 insertions(+), 43 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 31d10d77e58..5ee670be9f4 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -96,7 +96,7 @@ abstract_object_pointert abstract_environmentt::eval( std::dynamic_pointer_cast( eval(dereference.pointer(), ns)); - return pointer_abstract_object->read_dereference(*this); + return pointer_abstract_object->read_dereference(*this, ns); } }, { @@ -142,6 +142,7 @@ Function: abstract_environmentt::assign Inputs: expr - the expression to assign to value - the value to assign to the expression + ns - the namespace Outputs: A boolean, true if the assignment has changed the domain. @@ -150,7 +151,7 @@ Function: abstract_environmentt::assign \*******************************************************************/ bool abstract_environmentt::assign( - const exprt &expr, const abstract_object_pointert value) + const exprt &expr, const abstract_object_pointert value, const namespacet &ns) { assert(value); @@ -191,7 +192,7 @@ bool abstract_environmentt::assign( { symbol_object=map[symbol_expr]; } - final_value=write(symbol_object, value, stactions, false); + final_value=write(symbol_object, value, stactions, ns, false); } else { @@ -221,6 +222,7 @@ Function: abstract_object_pointert abstract_environmentt::write rhs - the value we are trying to write to the left hand side remaining_stack - what is left of the stack before the rhs can replace or be merged with the rhs + ns - the namespace merge_write - Are re replacing the left hand side with the right hand side (e.g. we know for a fact that we are overwriting this object) or could the write in fact not take place and therefore we @@ -234,10 +236,12 @@ Function: abstract_object_pointert abstract_environmentt::write abstract_pointer and abstract_array until the stack is empty \*******************************************************************/ + abstract_object_pointert abstract_environmentt::write( abstract_object_pointert lhs, abstract_object_pointert rhs, std::stack remaining_stack, + const namespacet &ns, bool merge_write) { assert(!remaining_stack.empty()); @@ -310,7 +314,7 @@ abstract_object_pointert abstract_environmentt::write( sharing_ptrt modified_pointer= pointer_abstract_object->write_dereference( - *this, stack, rhs_object, merge_write); + *this, ns, stack, rhs_object, merge_write); return modified_pointer; } diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index f7b9597410b..6b69c766c81 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -22,13 +22,18 @@ class abstract_environmentt // These three are really the heart of the method virtual abstract_object_pointert eval( const exprt &expr, const namespacet &ns) const; - virtual bool assign(const exprt &expr, const abstract_object_pointert value); + virtual bool assign( + const exprt &expr, + const abstract_object_pointert value, + const namespacet &ns); virtual bool assume(const exprt &expr, const namespacet &ns); - virtual abstract_object_pointert write(abstract_object_pointert lhs, - abstract_object_pointert rhs, - std::stack remaining_stack, - bool merge_write); + virtual abstract_object_pointert write( + abstract_object_pointert lhs, + abstract_object_pointert rhs, + std::stack remaining_stack, + const namespacet &ns, + bool merge_write); virtual abstract_object_pointert abstract_object_factory( const typet type, bool top=true, bool bottom=false) const; diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 58c738a5c29..7c050b0b903 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "constant_pointer_abstract_object.h" /*******************************************************************\ @@ -30,7 +31,7 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( pointer_abstract_objectt(t) { assert(t.id()==ID_pointer); - value=enviroment.abstract_object_factory(t.subtype(), true, false); + value=nil_exprt(); } /*******************************************************************\ @@ -54,7 +55,7 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( pointer_abstract_objectt(t, tp, bttm) { assert(t.id()==ID_pointer); - value=enviroment.abstract_object_factory(t.subtype(), top, bottom); + value=nil_exprt(); } /*******************************************************************\ @@ -100,8 +101,8 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( // can create a pointer if(e.id()==ID_address_of) { - address_of_exprt address_expr(to_address_of_expr(e)); - value=enviroment.eval(address_expr.object(), ns); + //address_of_exprt address_expr(to_address_of_expr(e)); + value=e; top=false; } else @@ -111,19 +112,19 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( constant_exprt constant_expr(to_constant_expr(e)); if(constant_expr.get_value()==ID_NULL) { - value=nullptr; + value=e; top=false; } else { // TODO(tkiley): These should probably be logged. // unknown type - value=enviroment.abstract_object_factory(type.subtype(), true, false); + value=nil_exprt(); } } else { - value=enviroment.abstract_object_factory(type.subtype(), true, false); + value=nil_exprt(); } } } @@ -163,7 +164,7 @@ bool constant_pointer_abstract_objectt::merge_state( else { top=true; - value=nullptr; + value=nil_exprt(); assert(!bottom); return !op1->top; } @@ -195,16 +196,9 @@ exprt constant_pointer_abstract_objectt::to_constant() const } else { - if(value==nullptr) - { - return null_pointer_exprt(to_pointer_type(type)); - } - else - { - const exprt &value_expr=value->to_constant(); - address_of_exprt address_expr(value_expr); - return address_expr; - } + // TODO(tkiley): I think we would like to eval this before using it + // in the to_constant. + return value; } } @@ -233,14 +227,25 @@ void constant_pointer_abstract_objectt::output( } else { - if(value==nullptr) + if(value.id()==ID_constant && value.get(ID_value)==ID_NULL) { out << "NULL"; } else { out << "ptr ->("; - value->output(out, ai, ns); + if(value.id()==ID_address_of) + { + const address_of_exprt &address_expr(to_address_of_expr(value)); + if(address_expr.object().id()==ID_symbol) + { + const symbol_exprt &symbol_pointed_to( + to_symbol_expr(address_expr.object())); + + out << symbol_pointed_to.get_identifier(); + } + } + out << ")"; } } @@ -252,6 +257,7 @@ Function: constant_pointer_abstract_objectt::read_dereference Inputs: env - the environment + ns - the namespace Outputs: An abstract object representing the value this pointer is pointing to @@ -263,18 +269,30 @@ Function: constant_pointer_abstract_objectt::read_dereference \*******************************************************************/ abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( - const abstract_environmentt &env) const + const abstract_environmentt &env, const namespacet &ns) const { - if(top || bottom || value==nullptr) + if(top || bottom || value.id()==ID_nil) { // Return top if dereferencing a null pointer or we are top - bool is_value_top = top || value==nullptr; + bool is_value_top = top || value.id()==ID_nil; return env.abstract_object_factory( type.subtype(), is_value_top, !is_value_top); } else { - return value; + if(value.id()==ID_address_of) + { + return env.eval(value.op0(), ns); + } + else if(value.id()==ID_constant) + { + // Reading a null pointer, return top + return env.abstract_object_factory(type.subtype(), true, false); + } + else + { + return env.abstract_object_factory(type.subtype(), true, false); + } } } @@ -284,6 +302,7 @@ Function: constant_pointer_abstract_objectt::write_dereference Inputs: environment - the environment + ns - the namespace stack - the remaining stack new_value - the value to write to the dereferenced pointer merging_write - is it a merging write (i.e. we aren't certain @@ -305,6 +324,7 @@ Function: constant_pointer_abstract_objectt::write_dereference sharing_ptrt constant_pointer_abstract_objectt::write_dereference( abstract_environmentt &environment, + const namespacet &ns, const std::stack stack, const abstract_object_pointert new_value, bool merging_write) @@ -312,7 +332,7 @@ sharing_ptrt if(top || bottom) { return pointer_abstract_objectt::write_dereference( - environment, stack, new_value, merging_write); + environment, ns, stack, new_value, merging_write); } else { @@ -324,19 +344,21 @@ sharing_ptrt if(merging_write) { + abstract_object_pointert pointed_value=environment.eval(value, ns); bool modifications; - copy->value=value->merge(new_value, modifications); + pointed_value->merge(new_value, modifications); } else { - copy->value=new_value; + environment.assign(value, new_value, ns); } return copy; } else { + abstract_object_pointert pointed_value=environment.eval(value, ns); return std::dynamic_pointer_cast( - environment.write(value, new_value, stack, merging_write)); + environment.write(pointed_value, new_value, stack, ns, merging_write)); } } } diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 3b156fd665a..1bd0f844d8a 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -43,16 +43,17 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt void output(std::ostream &out, const ai_baset &ai, const namespacet &ns); abstract_object_pointert read_dereference( - const abstract_environmentt &env) const; + const abstract_environmentt &env, const namespacet &ns) const; sharing_ptrt write_dereference( abstract_environmentt &environment, + const namespacet &ns, const std::stack stack, const abstract_object_pointert value, bool merging_write); private: - abstract_object_pointert value; + exprt value; }; diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index 3012cea5bc0..d6ae12eb3d5 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -98,6 +98,7 @@ Function: pointer_abstract_objectt::read_dereference Inputs: env - the environment + ns - the namespace Outputs: An abstract object representing the value being pointed to @@ -107,7 +108,7 @@ Function: pointer_abstract_objectt::read_dereference \*******************************************************************/ abstract_object_pointert pointer_abstract_objectt::read_dereference( - const abstract_environmentt &env) const + const abstract_environmentt &env, const namespacet &ns) const { pointer_typet pointer_type(to_pointer_type(type)); const typet &pointed_to_type=pointer_type.subtype(); @@ -121,6 +122,7 @@ Function: pointer_abstract_objectt::write_dereference Inputs: environment - the abstract environment + ns - the namespace stack - the remaining stack of expressions on the LHS to evaluate value - the value we are trying to assign to what the pointer is pointing to @@ -141,6 +143,7 @@ Function: pointer_abstract_objectt::write_dereference sharing_ptrt pointer_abstract_objectt::write_dereference( abstract_environmentt &environment, + const namespacet &ns, const std::stack stack, const abstract_object_pointert value, bool merging_write) diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index 8c4fa17e6b6..1d54706c9bc 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -30,10 +30,11 @@ class pointer_abstract_objectt:public abstract_objectt // pointer interface virtual abstract_object_pointert read_dereference( - const abstract_environmentt &env) const; + const abstract_environmentt &env, const namespacet &ns) const; virtual sharing_ptrt write_dereference( abstract_environmentt &environment, + const namespacet &ns, const std::stack stack, const abstract_object_pointert value, bool merging_write); diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 7736eef675d..575b57fe145 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -57,7 +57,8 @@ void variable_sensitivity_domaint::transform( abstract_object_pointert top_object= abstract_state.abstract_object_factory( to_code_dead(instruction.code).symbol().type(), true); - abstract_state.assign(to_code_dead(instruction.code).symbol(), top_object); + abstract_state.assign( + to_code_dead(instruction.code).symbol(), top_object, ns); } break; @@ -67,7 +68,7 @@ void variable_sensitivity_domaint::transform( // TODO : check return values abstract_object_pointert r = abstract_state.eval(inst.rhs(), ns); - abstract_state.assign(inst.lhs(), r); + abstract_state.assign(inst.lhs(), r, ns); } break; From 54923109f51b2bcc05eb544d953c4c206525ee8e Mon Sep 17 00:00:00 2001 From: Owen Jones Date: Tue, 28 Feb 2017 15:00:32 +0000 Subject: [PATCH 053/129] Implementing a configurable abstract object factory We must follow type to deal with struct problem. Structs work now without segfault --- src/analyses/Makefile | 1 + .../abstract_enviroment.cpp | 82 +++++------ .../abstract_enviroment.h | 24 ++-- .../variable-sensitivity/abstract_object.cpp | 2 +- .../array_abstract_object.cpp | 8 +- .../array_abstract_object.h | 6 +- .../constant_pointer_abstract_object.cpp | 6 +- .../pointer_abstract_object.cpp | 2 +- .../struct_abstract_object.cpp | 8 +- .../struct_abstract_object.h | 6 +- .../variable_sensitivity_domain.cpp | 2 +- .../variable_sensitivity_object_factory.cpp | 132 ++++++++++++++++++ .../variable_sensitivity_object_factory.h | 46 ++++++ .../goto_analyzer_parse_options.cpp | 5 + 14 files changed, 260 insertions(+), 70 deletions(-) create mode 100644 src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp create mode 100644 src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h diff --git a/src/analyses/Makefile b/src/analyses/Makefile index 2ed092359d7..0f3595b5e34 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -33,6 +33,7 @@ SRC = ai.cpp \ variable-sensitivity/pointer_abstract_object.cpp \ variable-sensitivity/struct_abstract_object.cpp \ variable-sensitivity/variable_sensitivity_domain.cpp \ + variable-sensitivity/variable_sensitivity_object_factory.cpp \ # Empty last line INCLUDES= -I .. diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 5ee670be9f4..f2e77af1775 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -13,8 +13,8 @@ #include #include #include -#include #include +#include #include #include @@ -22,7 +22,6 @@ #ifdef DEBUG #include #endif - /*******************************************************************\ Function: abstract_environmentt::eval @@ -51,7 +50,7 @@ abstract_object_pointert abstract_environmentt::eval( const auto &symbol_entry=map.find(symbol); if(symbol_entry==map.cend()) { - return abstract_object_factory(expr.type(), true); + return abstract_object_factory(expr.type(), ns, true); } else { @@ -74,7 +73,7 @@ abstract_object_pointert abstract_environmentt::eval( std::dynamic_pointer_cast( eval(member_expr.compound(), ns)); - return struct_abstract_object->read_component(*this, member_expr); + return struct_abstract_object->read_component(*this, member_expr, ns); } }, { @@ -107,7 +106,7 @@ abstract_object_pointert abstract_environmentt::eval( std::dynamic_pointer_cast( eval(index_expr.array(), ns)); - return array_abstract_object->read_index(*this, index_expr); + return array_abstract_object->read_index(*this, index_expr, ns); } } }; @@ -126,7 +125,7 @@ abstract_object_pointert abstract_environmentt::eval( } else { - return abstract_object_factory(simplified_expr.type(), true); + return abstract_object_factory(simplified_expr.type(), ns, true); } } else @@ -186,7 +185,8 @@ bool abstract_environmentt::assign( abstract_object_pointert symbol_object; if(map.find(symbol_expr)==map.end()) { - symbol_object=abstract_object_factory(symbol_expr.type(), true, false); + symbol_object=abstract_object_factory( + symbol_expr.type(), ns, true, false); } else { @@ -378,6 +378,7 @@ Function: abstract_environmentt::abstract_object_factory Inputs: type - the type of the object whose state should be tracked top - does the type of the object start as top + bottom - does the type of the object start as bottom in the two-value domain Outputs: The abstract object that has been created @@ -387,23 +388,10 @@ Function: abstract_environmentt::abstract_object_factory \*******************************************************************/ abstract_object_pointert abstract_environmentt::abstract_object_factory( - const typet type, bool top, bool bottom) const + const typet &type, const namespacet &ns, bool top, bool bottom) const { - // TODO (tkiley): Here we should look at some config file - if(type.id()==ID_signedbv || type.id()==ID_bool || type.id()==ID_c_bool) - { - return abstract_object_pointert( - new constant_abstract_valuet(type, top, bottom)); - } - else if(type.id()==ID_pointer) - { - return abstract_object_pointert( - new constant_pointer_abstract_objectt(type, top, bottom, *this)); - } - else - { - return abstract_object_pointert(new abstract_objectt(type, top, false)); - } + exprt empty_constant_expr=exprt(); + return abstract_object_factory(type, top, bottom, empty_constant_expr, ns); } /*******************************************************************\ @@ -422,23 +410,34 @@ Function: abstract_environmentt::abstract_object_factory \*******************************************************************/ abstract_object_pointert abstract_environmentt::abstract_object_factory( - const typet type, const exprt e, const namespacet &ns) const + const typet &type, const exprt &e, const namespacet &ns) const { - assert(type==e.type()); - if(type.id()==ID_signedbv || type.id()==ID_bool || type.id()==ID_c_bool) - { - return abstract_object_pointert( - new constant_abstract_valuet(e)); - } - else if(type.id()==ID_pointer) - { - return abstract_object_pointert( - new constant_pointer_abstract_objectt(e, *this, ns)); - } - else - { - return abstract_object_pointert(new abstract_objectt(e)); - } + return abstract_object_factory(type, false, false, e, ns); +} + +/*******************************************************************\ + +Function: abstract_environmentt::abstract_object_factory + + Inputs: + type - the type of the object whose state should be tracked + top - does the type of the object start as top in the two-value domain + bottom - does the type of the object start as bottom in the two-value domain + expr - the starting value of the symbol if top and bottom are both false + + Outputs: The abstract object that has been created + + Purpose: Look at the configuration for the sensitivity and create an + appropriate abstract_object + +\*******************************************************************/ + +abstract_object_pointert abstract_environmentt::abstract_object_factory( + const typet &type, bool top, bool bottom, const exprt &e, + const namespacet &ns) const +{ + return variable_sensitivity_object_factoryt::instance().get_abstract_object( + type, top, bottom, e, ns); } /*******************************************************************\ @@ -651,8 +650,3 @@ abstract_object_pointert abstract_environmentt::eval_expression( abstract_object_pointert lhs=eval(e.op0(), ns); return lhs->expression_transform(e, *this, ns); } - -abstract_object_pointert abstract_environmentt::eval_rest(const exprt &e) const -{ - return abstract_object_factory(e.type()); -} diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 6b69c766c81..4b65aeab3ec 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -5,6 +5,7 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ + #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_ENVIROMENT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_ENVIROMENT_H @@ -36,17 +37,21 @@ class abstract_environmentt bool merge_write); virtual abstract_object_pointert abstract_object_factory( - const typet type, bool top=true, bool bottom=false) const; + const typet &type, + const namespacet &ns, + bool top=true, + bool bottom=false) const; // For converting constants in the program // Maybe these two should be compacted to one call... virtual abstract_object_pointert abstract_object_factory( - const typet type, const exprt e, const namespacet &ns) const; + const typet &type, const exprt &e, const namespacet &ns) const; virtual bool merge(const abstract_environmentt &env); // This should be used as a default case / everything else has failed - // The string is so that I can easily find and diagnose cases where this occurs + // The string is so that I can easily find and diagnose cases where this + // occurs virtual void havoc(const std::string &havoc_string); void make_top(); @@ -65,14 +70,13 @@ class abstract_environmentt virtual abstract_object_pointert eval_expression( const exprt &e, const namespacet &ns) const; - // Hook for domain specific handling of operators - virtual abstract_object_pointert eval_rest(const exprt &e) const; - - - - typedef symbol_exprt map_keyt; - std::map map; + typedef symbol_exprt map_keyt; + std::map map; +private: + abstract_object_pointert abstract_object_factory( + const typet &type, bool top, bool bottom, const exprt &e, + const namespacet &ns) const; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_ENVIROMENT_H diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 1e836632ce3..981c893c6c9 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -201,7 +201,7 @@ abstract_object_pointert abstract_objectt::expression_transform( } else { - return environment.abstract_object_factory(expr.type(), true, false); + return environment.abstract_object_factory(expr.type(), ns, true, false); } } diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 99430ad9044..13cc0cb9e55 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -85,7 +85,7 @@ Function: array_abstract_objectt::array_abstract_objectt \*******************************************************************/ -array_abstract_objectt::array_abstract_objectt(const constant_exprt &e): +array_abstract_objectt::array_abstract_objectt(const exprt &e): abstract_objectt(e) { assert(e.type().id()==ID_array); @@ -107,14 +107,16 @@ Function: array_abstract_objectt::read_index \*******************************************************************/ abstract_object_pointert array_abstract_objectt::read_index( - const abstract_environmentt &env, const index_exprt &index) const + const abstract_environmentt &env, + const index_exprt &index, + const namespacet& ns) const { array_typet array_type(to_array_type(type)); const typet &subtype=array_type.subtype(); // if we are bottom then so are the values in the array // otherwise the values are top - return env.abstract_object_factory(subtype, !is_bottom(), is_bottom()); + return env.abstract_object_factory(subtype, ns, !is_bottom(), is_bottom()); } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index 3af79165863..f4f19903ccc 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -22,13 +22,15 @@ class array_abstract_objectt:public abstract_objectt explicit array_abstract_objectt(const typet &type); array_abstract_objectt(const typet &type, bool top, bool bottom); explicit array_abstract_objectt(const array_abstract_objectt &old); - explicit array_abstract_objectt(const constant_exprt &expr); + explicit array_abstract_objectt(const exprt &expr); CLONE MERGE(abstract_objectt) virtual abstract_object_pointert read_index( - const abstract_environmentt &env, const index_exprt &index) const; + const abstract_environmentt &env, + const index_exprt &index, + const namespacet &ns) const; virtual sharing_ptrt write_index( abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 7c050b0b903..967df56a3a7 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -276,7 +276,7 @@ abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( // Return top if dereferencing a null pointer or we are top bool is_value_top = top || value.id()==ID_nil; return env.abstract_object_factory( - type.subtype(), is_value_top, !is_value_top); + type.subtype(), ns, is_value_top, !is_value_top); } else { @@ -287,11 +287,11 @@ abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( else if(value.id()==ID_constant) { // Reading a null pointer, return top - return env.abstract_object_factory(type.subtype(), true, false); + return env.abstract_object_factory(type.subtype(), ns, true, false); } else { - return env.abstract_object_factory(type.subtype(), true, false); + return env.abstract_object_factory(type.subtype(), ns, true, false); } } } diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index d6ae12eb3d5..448623583f8 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -113,7 +113,7 @@ abstract_object_pointert pointer_abstract_objectt::read_dereference( pointer_typet pointer_type(to_pointer_type(type)); const typet &pointed_to_type=pointer_type.subtype(); - return env.abstract_object_factory(pointed_to_type, true, false); + return env.abstract_object_factory(pointed_to_type, ns, true, false); } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index 83a0e966e28..4ebe07d440d 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -86,7 +86,7 @@ Function: struct_abstract_objectt::struct_abstract_objectt \*******************************************************************/ -struct_abstract_objectt::struct_abstract_objectt(const constant_exprt &e): +struct_abstract_objectt::struct_abstract_objectt(const exprt &e): abstract_objectt(e) { assert(e.type().id()==ID_struct); @@ -111,12 +111,14 @@ Function: struct_abstract_objectt::read_component \*******************************************************************/ abstract_object_pointert struct_abstract_objectt::read_component( - const abstract_environmentt &environment, const member_exprt &member_expr) + const abstract_environmentt &environment, + const member_exprt &member_expr, + const namespacet& ns) { // If we are bottom then so are the components // otherwise the components could be anything return environment.abstract_object_factory( - member_expr.type(), !is_bottom(), is_bottom()); + member_expr.type(), ns, !is_bottom(), is_bottom()); } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index 16a02ca9d0a..9b9cb55d0b6 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -21,14 +21,16 @@ class struct_abstract_objectt:public abstract_objectt explicit struct_abstract_objectt(const typet &type); struct_abstract_objectt(const typet &type, bool top, bool bottom); explicit struct_abstract_objectt(const struct_abstract_objectt &old); - explicit struct_abstract_objectt(const constant_exprt &expr); + explicit struct_abstract_objectt(const exprt &expr); CLONE MERGE(abstract_objectt) // struct interface virtual abstract_object_pointert read_component( - const abstract_environmentt &environment, const member_exprt &member_expr); + const abstract_environmentt &environment, + const member_exprt &member_expr, + const namespacet& ns); virtual sharing_ptrt write_component( const abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 575b57fe145..1268facf9e2 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -56,7 +56,7 @@ void variable_sensitivity_domaint::transform( // Assign to top is the same as removing abstract_object_pointert top_object= abstract_state.abstract_object_factory( - to_code_dead(instruction.code).symbol().type(), true); + to_code_dead(instruction.code).symbol().type(), ns, true); abstract_state.assign( to_code_dead(instruction.code).symbol(), top_object, ns); } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp new file mode 100644 index 00000000000..ad2dc26d304 --- /dev/null +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -0,0 +1,132 @@ +#include "variable_sensitivity_object_factory.h" +#include "util/namespace.h" + +variable_sensitivity_object_factoryt + variable_sensitivity_object_factoryt::s_instance; + +variable_sensitivity_object_factoryt::ABSTRACT_OBJECT_TYPET + variable_sensitivity_object_factoryt::get_abstract_object_type( + const typet type, const namespacet &ns) +{ + ABSTRACT_OBJECT_TYPET abstract_object_type=TWO_VALUE; + + if(type.id()==ID_signedbv || type.id()==ID_unsignedbv || + type.id()==ID_floatbv || type.id()==ID_fixedbv || + type.id()==ID_c_bool) + { + abstract_object_type=CONSTANT; + } + else if(type.id()==ID_array) + { + if(has_arrays_flag) + { + abstract_object_type=ARRAY_SENSITIVE; + } + else + { + abstract_object_type=ARRAY_INSENSITIVE; + } + } + else if(type.id()==ID_pointer) + { + if(has_pointers_flag) + { + abstract_object_type=POINTER_SENSITIVE; + } + else + { + abstract_object_type=POINTER_INSENSITIVE; + } + } + else if(type.id()==ID_struct) + { + if(has_structs_flag) + { + abstract_object_type=STRUCT_SENSITIVE; + } + else + { + abstract_object_type=STRUCT_INSENSITIVE; + } + } + + // TODO: deal with unions + return abstract_object_type; +} + + +abstract_object_pointert variable_sensitivity_object_factoryt:: + get_abstract_object( + const typet type, bool top, bool bottom, const exprt &e, + const namespacet &ns) +{ + typet followed_type = ns.follow(type); + ABSTRACT_OBJECT_TYPET abstract_object_type=get_abstract_object_type(followed_type, ns); + + if(top || bottom) + { + switch(abstract_object_type) + { + case CONSTANT: + return abstract_object_pointert( + new constant_abstract_valuet(followed_type, top, bottom)); + case ARRAY_SENSITIVE: + return abstract_object_pointert( + new array_abstract_objectt(followed_type, top, false)); + case ARRAY_INSENSITIVE: + return abstract_object_pointert( + new array_abstract_objectt(followed_type, top, false)); + case POINTER_SENSITIVE: + return abstract_object_pointert( + new pointer_abstract_objectt(followed_type, top, false)); + case POINTER_INSENSITIVE: + return abstract_object_pointert( + new pointer_abstract_objectt(followed_type, top, false)); + case STRUCT_SENSITIVE: + return abstract_object_pointert( + new struct_abstract_objectt(followed_type, top, false)); + case STRUCT_INSENSITIVE: + return abstract_object_pointert( + new struct_abstract_objectt(followed_type, top, false)); + case TWO_VALUE: + return abstract_object_pointert(new abstract_objectt(followed_type, top, false)); + default: + assert(false); + return abstract_object_pointert(new abstract_objectt(followed_type, top, false)); + } + } + else + { + assert(followed_type==e.type()); + switch(abstract_object_type) + { + case CONSTANT: + return abstract_object_pointert(new constant_abstract_valuet(e)); + case ARRAY_SENSITIVE: + return abstract_object_pointert(new array_abstract_objectt(e)); + case ARRAY_INSENSITIVE: + return abstract_object_pointert(new array_abstract_objectt(e)); + case POINTER_SENSITIVE: + return abstract_object_pointert(new pointer_abstract_objectt(e)); + case POINTER_INSENSITIVE: + return abstract_object_pointert(new pointer_abstract_objectt(e)); + case STRUCT_SENSITIVE: + return abstract_object_pointert(new struct_abstract_objectt(e)); + case STRUCT_INSENSITIVE: + return abstract_object_pointert(new struct_abstract_objectt(e)); + case TWO_VALUE: + return abstract_object_pointert(new abstract_objectt(e)); + default: + assert(false); + return abstract_object_pointert(new abstract_objectt(e)); + } + } +} + +void variable_sensitivity_object_factoryt::set_options(optionst &options) +{ + has_variables_flag=options.get_bool_option("variable"); + has_structs_flag=options.get_bool_option("structs"); + has_arrays_flag=options.get_bool_option("arrays"); + has_pointers_flag=options.get_bool_option("pointers"); +} diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h new file mode 100644 index 00000000000..3d02436ef67 --- /dev/null +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -0,0 +1,46 @@ +#ifndef VARIABLE_SENSITIVITY_OBJECT_FACTORY_H +#define VARIABLE_SENSITIVITY_OBJECT_FACTORY_H + +#include +#include +#include +#include +#include + + +class variable_sensitivity_object_factoryt +{ +public: + static variable_sensitivity_object_factoryt &instance() + { + return s_instance; + } + abstract_object_pointert get_abstract_object( + const typet type, bool top, bool bottom, const exprt &e, + const namespacet &ns); + void set_options(optionst &options); + +private: + variable_sensitivity_object_factoryt() + {} + static variable_sensitivity_object_factoryt s_instance; + enum ABSTRACT_OBJECT_TYPET + { + TWO_VALUE, + CONSTANT, + ARRAY_SENSITIVE, + ARRAY_INSENSITIVE, + POINTER_SENSITIVE, + POINTER_INSENSITIVE, + STRUCT_SENSITIVE, + STRUCT_INSENSITIVE + }; + ABSTRACT_OBJECT_TYPET get_abstract_object_type( + const typet type, const namespacet &ns); + bool has_variables_flag; + bool has_structs_flag; + bool has_arrays_flag; + bool has_pointers_flag; +}; + +#endif // VARIABLE_SENSITIVITY_OBJECT_FACTORY_H diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index 6dc43b54701..db6cb03de21 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -49,6 +49,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include + #include #include "goto_analyzer_parse_options.h" @@ -414,6 +416,9 @@ int goto_analyzer_parse_optionst::doit() if(set_properties()) return 7; + // Store options in static variable_sensitivity_object_factory object + variable_sensitivity_object_factoryt::instance().set_options(options); + // Output file factory std::ostream *out; const std::string outfile=options.get_option("outfile"); From 70ae194ad3d14d8ecd9f95f47df6b9a70c2813f8 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 18:43:11 +0000 Subject: [PATCH 054/129] Fixed crash bug in writing to dereference of pointer to pointer Fixed a number of issues with pointer to pointer that were out by one (dereference). Specifically, when we are writing to a dereference, the pointer itself remains unchanged, so what we return from the write dereference is just a clone of te pointer. When reading, we don't eval the address_of exprt as don't know how to handle this, instead we eval the object of the address of (since we are dereferencing to call the read_dereference function anyway). --- .../constant_pointer_abstract_object.cpp | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 967df56a3a7..f00f4bc5bf2 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -336,29 +336,45 @@ sharing_ptrt } else { + // If not an address, we don't know what we are pointing to + if(value.id()!=ID_address_of) + { + return pointer_abstract_objectt::write_dereference( + environment, ns, stack, new_value, merging_write); + } + + const address_of_exprt &address_expr=to_address_of_expr(value); + + sharing_ptrt copy= + sharing_ptrt( + new constant_pointer_abstract_objectt(*this)); + if(stack.empty()) { - sharing_ptrt copy= - sharing_ptrt( - new constant_pointer_abstract_objectt(*this)); + // We should not be changing the type of an abstract object + assert(new_value->get_type()==type.subtype()); + if(merging_write) { - abstract_object_pointert pointed_value=environment.eval(value, ns); + abstract_object_pointert pointed_value= + environment.eval(address_expr.object(), ns); bool modifications; pointed_value->merge(new_value, modifications); } else { - environment.assign(value, new_value, ns); + environment.assign(address_expr.object(), new_value, ns); } - return copy; } else { - abstract_object_pointert pointed_value=environment.eval(value, ns); - return std::dynamic_pointer_cast( - environment.write(pointed_value, new_value, stack, ns, merging_write)); + abstract_object_pointert pointed_value= + environment.eval(address_expr.object(), ns); + environment.write(pointed_value, new_value, stack, ns, merging_write); + + // but the pointer itself does not change! } + return copy; } } From 6c89bf23543fb7197f3fbc9b3085d5d9ddd84e9b Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 18:45:11 +0000 Subject: [PATCH 055/129] Improved exception message for unreasonable write --- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index f2e77af1775..4f8a944678c 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -169,7 +170,10 @@ bool abstract_environmentt::assign( { // Attempting to assign to something unreasonable // Your goto-program is broken - throw "die_horribly"; + std::ostringstream error_builder; + error_builder << "unsupported assign "; + error_builder << s.id(); + throw error_builder.str(); } } From 079eed931f58a994d92b3f1dfe9520ad51eeec9b Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 16:24:35 +0000 Subject: [PATCH 056/129] Checking in a demo script containg the things that currently work Demo includes - being aware if if statement is taken - pointer sensitivity, pointer to pointer working - assertions relating to both the pointers value and what it's pointing to - simplification able to remove assignment to a pointer --- regression/goto-analyzer/demo/main.c | 59 ++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 regression/goto-analyzer/demo/main.c diff --git a/regression/goto-analyzer/demo/main.c b/regression/goto-analyzer/demo/main.c new file mode 100644 index 00000000000..3c5240787a3 --- /dev/null +++ b/regression/goto-analyzer/demo/main.c @@ -0,0 +1,59 @@ +#include + +int main() +{ + func(4); +} + + +// Pass in an unknown to show when we don't know what branch is taken +void func(int unknown) +{ + int i=0, j=2; + if (i==0) + { + i++; + j++; + } + + // Knows we took if statement so can conclude assertion is true + assert(j==2); + + int value=4; + + int * p2v = &value; + int ** pp2v = &p2v; + + assert(*p2v==4); + assert(**pp2v==4); + + value=10; + + // Tracks the value pointed to has changed + assert(*p2v==10); + assert(**pp2v==10); + + int other = 5; + p2v = &other; + + assert(*p2v==5); + assert(**pp2v==5); + + if(unknown > 10) + { + p2v = &value; + } + else + { + p2v = &other; + } + + assert(pp2v==&p2v); // success (even though p2v has changed) + assert(*p2v==10); // unknown since we don't know anymore what p2v points to + assert(**pp2v==10); // unknown + + // Run with --simplify says yp = &x + int x = 4; + int * xp = &x; + int * yp = xp; +} \ No newline at end of file From c0c7c0df02694139116b3ce9c1ffad63166a3a8a Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 18:45:51 +0000 Subject: [PATCH 057/129] Added writing to pointer to demo --- regression/goto-analyzer/demo/main.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/regression/goto-analyzer/demo/main.c b/regression/goto-analyzer/demo/main.c index 3c5240787a3..11894c2c34c 100644 --- a/regression/goto-analyzer/demo/main.c +++ b/regression/goto-analyzer/demo/main.c @@ -1,5 +1,6 @@ #include +void func(int unknwon); int main() { func(4); @@ -7,6 +8,7 @@ int main() // Pass in an unknown to show when we don't know what branch is taken + void func(int unknown) { int i=0, j=2; @@ -33,6 +35,16 @@ void func(int unknown) assert(*p2v==10); assert(**pp2v==10); + *p2v = 15; + assert(value==15); + assert(*p2v==15); + assert(**pp2v==15); + + **pp2v = 20; + assert(value==20); + assert(*p2v==20); + assert(**pp2v==20); + int other = 5; p2v = &other; @@ -51,9 +63,8 @@ void func(int unknown) assert(pp2v==&p2v); // success (even though p2v has changed) assert(*p2v==10); // unknown since we don't know anymore what p2v points to assert(**pp2v==10); // unknown - // Run with --simplify says yp = &x int x = 4; int * xp = &x; int * yp = xp; -} \ No newline at end of file +} From 1843fecc0df690236c782f974c5168b8f28fc615 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 19:18:33 +0000 Subject: [PATCH 058/129] Added flags so the factory reads the flags correctly --- src/goto-analyzer/goto_analyzer_parse_options.cpp | 5 +++++ src/goto-analyzer/goto_analyzer_parse_options.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index db6cb03de21..dadf7d6fb6f 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -243,6 +243,11 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) if(cmdline.isset("ignore-unresolved-calls")) options.set_option("ignore-unresolved-calls", true); + + // Configuration of variable sensitivity + options.set_option("pointers", cmdline.isset("pointers")); + options.set_option("arrays", cmdline.isset("arrays")); + options.set_option("structs", cmdline.isset("structs")); } /// invoke main modules diff --git a/src/goto-analyzer/goto_analyzer_parse_options.h b/src/goto-analyzer/goto_analyzer_parse_options.h index bbc64edf3ed..94aa25babda 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.h +++ b/src/goto-analyzer/goto_analyzer_parse_options.h @@ -139,6 +139,7 @@ class optionst; "(intervals)(show-intervals)" \ "(non-null)(show-non-null)" \ "(variable)" \ + "(pointers)(arrays)(structs)" \ "(constants)" \ "(dependence-graph)" \ "(show)(verify)(simplify):" \ From 847a2af86b621183c24dfa93f9c85d1c774b717a Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 19:18:59 +0000 Subject: [PATCH 059/129] Enable pointer sensitivity in the factory Also turn on the test for checking it. Fixed a few interface mistakes in the class. --- .../sensitivity-test-constants-char/test.desc | 2 +- .../sensitivity-test-constants-float/test.desc | 2 +- .../test.desc | 2 +- .../sensitivity-test-constants-pointer/test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../sensitivity-test-two-value-pointer/test.desc | 2 +- .../constant_pointer_abstract_object.cpp | 8 +++----- .../constant_pointer_abstract_object.h | 11 ++++------- .../variable_sensitivity_object_factory.cpp | 5 +++-- .../variable_sensitivity_object_factory.h | 1 + 12 files changed, 19 insertions(+), 22 deletions(-) diff --git a/regression/goto-analyzer/sensitivity-test-constants-char/test.desc b/regression/goto-analyzer/sensitivity-test-constants-char/test.desc index 4ae7832010b..a74c6c89412 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-char/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-char/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_char.c --variable --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-float/test.desc b/regression/goto-analyzer/sensitivity-test-constants-float/test.desc index 634ea862f56..afa66b0ec00 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-float/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-float/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_float.c --variable --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/test.desc index f7fa1706d6a..0a001aa5642 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_pointer_to_constants_pointer.c --variable --pointers --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc index 22c179f2233..657e621a90f 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_pointer.c --variable --pointers --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc index 974705f9fc1..58bedcf1cc1 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_two_value_pointer_to_two_value_array.c --variable --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/test.desc index e3582834688..8ea26dbd7e9 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_two_value_pointer_to_two_value_pointer.c --variable --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/test.desc index 56a0be48407..17853721fc2 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_two_value_pointer_to_two_value_struct.c --variable --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer/test.desc index da9abe2464f..97be4873c1a 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_two_value_pointer.c --variable --verify ^EXIT=0$ diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index f00f4bc5bf2..b7f023f2f41 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -27,7 +27,7 @@ Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt \*******************************************************************/ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( - const typet &t, const abstract_environmentt &enviroment): + const typet &t): pointer_abstract_objectt(t) { assert(t.id()==ID_pointer); @@ -51,7 +51,7 @@ Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt \*******************************************************************/ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( - const typet &t, bool tp, bool bttm, const abstract_environmentt &enviroment): + const typet &t, bool tp, bool bttm): pointer_abstract_objectt(t, tp, bttm) { assert(t.id()==ID_pointer); @@ -90,9 +90,7 @@ Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt \*******************************************************************/ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( - const exprt &e, - const abstract_environmentt &enviroment, - const namespacet &ns): + const exprt &e): pointer_abstract_objectt(e) { assert(e.type().id()==ID_pointer); diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 1bd0f844d8a..44e996d6c3d 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -16,21 +16,17 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt typedef sharing_ptrt constant_pointer_abstract_pointert; public: - constant_pointer_abstract_objectt( - const typet &type, const abstract_environmentt &enviroment); + constant_pointer_abstract_objectt(const typet &type); constant_pointer_abstract_objectt( const typet &type, bool top, - bool bottom, const abstract_environmentt &enviroment); + bool bottom); constant_pointer_abstract_objectt( const constant_pointer_abstract_objectt &old); - constant_pointer_abstract_objectt( - const exprt &expr, - const abstract_environmentt &enviroment, - const namespacet &ns); + constant_pointer_abstract_objectt(const exprt &expr); CLONE MERGE(pointer_abstract_objectt) @@ -56,6 +52,7 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt exprt value; + }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_POINTER_ABSTRACT_OBJECT_H // NOLINT(*) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index ad2dc26d304..cdb63ae694e 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -78,7 +78,7 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: new array_abstract_objectt(followed_type, top, false)); case POINTER_SENSITIVE: return abstract_object_pointert( - new pointer_abstract_objectt(followed_type, top, false)); + new constant_pointer_abstract_objectt(followed_type, top, false)); case POINTER_INSENSITIVE: return abstract_object_pointert( new pointer_abstract_objectt(followed_type, top, false)); @@ -107,7 +107,8 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: case ARRAY_INSENSITIVE: return abstract_object_pointert(new array_abstract_objectt(e)); case POINTER_SENSITIVE: - return abstract_object_pointert(new pointer_abstract_objectt(e)); + return abstract_object_pointert( + new constant_pointer_abstract_objectt(e)); case POINTER_INSENSITIVE: return abstract_object_pointert(new pointer_abstract_objectt(e)); case STRUCT_SENSITIVE: diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index 3d02436ef67..520756e5bf4 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -5,6 +5,7 @@ #include #include #include +#include #include From 23e19cc9911900da862c64effeaa856bca049f49 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 19:30:29 +0000 Subject: [PATCH 060/129] Added documentation to the demo script --- regression/goto-analyzer/demo/main.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/regression/goto-analyzer/demo/main.c b/regression/goto-analyzer/demo/main.c index 11894c2c34c..24e20e280ae 100644 --- a/regression/goto-analyzer/demo/main.c +++ b/regression/goto-analyzer/demo/main.c @@ -1,5 +1,14 @@ #include + +// To demonstrate run +// $ goto-analyzer main.c --variable --verify --pointers --structs +// Will show the asserts + +// To see the pointer optimizations run +// $ goto-analyzer main.c --variable --simplify out.gb --pointers --structs +// $ goto-analyzer out.gb --show-goto-functions + void func(int unknwon); int main() { @@ -19,7 +28,7 @@ void func(int unknown) } // Knows we took if statement so can conclude assertion is true - assert(j==2); + assert(j==3); // Verified int value=4; @@ -63,7 +72,9 @@ void func(int unknown) assert(pp2v==&p2v); // success (even though p2v has changed) assert(*p2v==10); // unknown since we don't know anymore what p2v points to assert(**pp2v==10); // unknown - // Run with --simplify says yp = &x + + // Running this through --simplify will yield: + // yp = &x int x = 4; int * xp = &x; int * yp = xp; From 80f7153184f2a6b280d4dd23c24d8cec377285c7 Mon Sep 17 00:00:00 2001 From: Owen Jones Date: Thu, 2 Mar 2017 15:56:32 +0000 Subject: [PATCH 061/129] Fixing up formatting Fixed up formatting of the abstract object factory. A few minor improvements as well --- .../variable_sensitivity_object_factory.cpp | 189 ++++++++++-------- .../variable_sensitivity_object_factory.h | 63 +++++- 2 files changed, 161 insertions(+), 91 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index cdb63ae694e..fb034763ef1 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -1,12 +1,32 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Owen Jones, owen.jones@diffblue.com + +\*******************************************************************/ #include "variable_sensitivity_object_factory.h" #include "util/namespace.h" variable_sensitivity_object_factoryt variable_sensitivity_object_factoryt::s_instance; +/*******************************************************************\ + +Function: variable_sensitivity_object_factoryt::get_abstract_object_type + + Inputs: + type - the type of the variable the abstract object is meant to represent + + Outputs: An enum indicating the abstract object type to use. + + Purpose: Decide which abstract object type to use for the variable in question. + +\*******************************************************************/ + variable_sensitivity_object_factoryt::ABSTRACT_OBJECT_TYPET variable_sensitivity_object_factoryt::get_abstract_object_type( - const typet type, const namespacet &ns) + const typet type) { ABSTRACT_OBJECT_TYPET abstract_object_type=TWO_VALUE; @@ -18,116 +38,115 @@ variable_sensitivity_object_factoryt::ABSTRACT_OBJECT_TYPET } else if(type.id()==ID_array) { - if(has_arrays_flag) - { - abstract_object_type=ARRAY_SENSITIVE; - } - else - { - abstract_object_type=ARRAY_INSENSITIVE; - } + abstract_object_type=has_arrays_flag?ARRAY_SENSITIVE:ARRAY_INSENSITIVE; } else if(type.id()==ID_pointer) { - if(has_pointers_flag) - { - abstract_object_type=POINTER_SENSITIVE; - } - else - { - abstract_object_type=POINTER_INSENSITIVE; - } + abstract_object_type= + has_pointers_flag?POINTER_SENSITIVE:POINTER_INSENSITIVE; } else if(type.id()==ID_struct) { - if(has_structs_flag) - { - abstract_object_type=STRUCT_SENSITIVE; - } - else - { - abstract_object_type=STRUCT_INSENSITIVE; - } + abstract_object_type=has_structs_flag?STRUCT_SENSITIVE:STRUCT_INSENSITIVE; + } + else if(type.id()==ID_union) + { + // TODO: deal with unions } - // TODO: deal with unions return abstract_object_type; } +/*******************************************************************\ + +Function: variable_sensitivity_object_factoryt::get_abstract_object + + Inputs: + type - the type of the variable + top - whether the abstract object should be top in the two-value domain + bottom - whether the abstract object should be bottom in the two-value domain + e - if top and bottom are false this expression is used as the starting + pointer for the abstract object + ns - namespace, used when following the input type + + Outputs: An abstract object of the appropriate type. + + Purpose: Get the appropriate abstract object for the variable under + consideration. + +\*******************************************************************/ abstract_object_pointert variable_sensitivity_object_factoryt:: get_abstract_object( - const typet type, bool top, bool bottom, const exprt &e, + const typet type, + bool top, + bool bottom, + const exprt &e, const namespacet &ns) { - typet followed_type = ns.follow(type); - ABSTRACT_OBJECT_TYPET abstract_object_type=get_abstract_object_type(followed_type, ns); - - if(top || bottom) + if(!initialized) { - switch(abstract_object_type) - { - case CONSTANT: - return abstract_object_pointert( - new constant_abstract_valuet(followed_type, top, bottom)); - case ARRAY_SENSITIVE: - return abstract_object_pointert( - new array_abstract_objectt(followed_type, top, false)); - case ARRAY_INSENSITIVE: - return abstract_object_pointert( - new array_abstract_objectt(followed_type, top, false)); - case POINTER_SENSITIVE: - return abstract_object_pointert( - new constant_pointer_abstract_objectt(followed_type, top, false)); - case POINTER_INSENSITIVE: - return abstract_object_pointert( - new pointer_abstract_objectt(followed_type, top, false)); - case STRUCT_SENSITIVE: - return abstract_object_pointert( - new struct_abstract_objectt(followed_type, top, false)); - case STRUCT_INSENSITIVE: - return abstract_object_pointert( - new struct_abstract_objectt(followed_type, top, false)); - case TWO_VALUE: - return abstract_object_pointert(new abstract_objectt(followed_type, top, false)); - default: - assert(false); - return abstract_object_pointert(new abstract_objectt(followed_type, top, false)); - } + throw "variable_sensitivity_object_factoryt::get_abstract_object() " \ + "called without first calling " \ + "variable_sensitivity_object_factoryt::set_options()\n"; } - else + + typet followed_type=ns.follow(type); + ABSTRACT_OBJECT_TYPET abstract_object_type= + get_abstract_object_type(followed_type); + + switch(abstract_object_type) { - assert(followed_type==e.type()); - switch(abstract_object_type) - { - case CONSTANT: - return abstract_object_pointert(new constant_abstract_valuet(e)); - case ARRAY_SENSITIVE: - return abstract_object_pointert(new array_abstract_objectt(e)); - case ARRAY_INSENSITIVE: - return abstract_object_pointert(new array_abstract_objectt(e)); - case POINTER_SENSITIVE: - return abstract_object_pointert( - new constant_pointer_abstract_objectt(e)); - case POINTER_INSENSITIVE: - return abstract_object_pointert(new pointer_abstract_objectt(e)); - case STRUCT_SENSITIVE: - return abstract_object_pointert(new struct_abstract_objectt(e)); - case STRUCT_INSENSITIVE: - return abstract_object_pointert(new struct_abstract_objectt(e)); - case TWO_VALUE: - return abstract_object_pointert(new abstract_objectt(e)); - default: - assert(false); - return abstract_object_pointert(new abstract_objectt(e)); - } + case CONSTANT: + return initialize_abstract_object( + followed_type, top, bottom, e, ns); + case ARRAY_SENSITIVE: + return initialize_abstract_object( + followed_type, top, bottom, e, ns); + case ARRAY_INSENSITIVE: + return initialize_abstract_object( + followed_type, top, bottom, e, ns); + case POINTER_SENSITIVE: + return initialize_abstract_object( + followed_type, top, bottom, e, ns); + case POINTER_INSENSITIVE: + return initialize_abstract_object( + followed_type, top, bottom, e, ns); + case STRUCT_SENSITIVE: + return initialize_abstract_object( + followed_type, top, bottom, e, ns); + case STRUCT_INSENSITIVE: + return initialize_abstract_object( + followed_type, top, bottom, e, ns); + case TWO_VALUE: + return initialize_abstract_object( + followed_type, top, bottom, e, ns); + default: + assert(false); + return initialize_abstract_object( + followed_type, top, bottom, e, ns); } } +/*******************************************************************\ + +Function: variable_sensitivity_object_factoryt::set_options + + Inputs: + options - the command line options + + Outputs: + + Purpose: Called once to record the appropriate variables from the command line + options so that they can be accessed easily when they are needed. + +\*******************************************************************/ + void variable_sensitivity_object_factoryt::set_options(optionst &options) { has_variables_flag=options.get_bool_option("variable"); has_structs_flag=options.get_bool_option("structs"); has_arrays_flag=options.get_bool_option("arrays"); has_pointers_flag=options.get_bool_option("pointers"); + initialized=true; } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index 520756e5bf4..21346d01413 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -1,5 +1,12 @@ -#ifndef VARIABLE_SENSITIVITY_OBJECT_FACTORY_H -#define VARIABLE_SENSITIVITY_OBJECT_FACTORY_H +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Owen Jones owen.jones@diffblue.com + +\*******************************************************************/ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_OBJECT_FACTORY_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_OBJECT_FACTORY_H #include #include @@ -22,7 +29,7 @@ class variable_sensitivity_object_factoryt void set_options(optionst &options); private: - variable_sensitivity_object_factoryt() + variable_sensitivity_object_factoryt():initialized(false) {} static variable_sensitivity_object_factoryt s_instance; enum ABSTRACT_OBJECT_TYPET @@ -36,12 +43,56 @@ class variable_sensitivity_object_factoryt STRUCT_SENSITIVE, STRUCT_INSENSITIVE }; - ABSTRACT_OBJECT_TYPET get_abstract_object_type( - const typet type, const namespacet &ns); + ABSTRACT_OBJECT_TYPET get_abstract_object_type(const typet type); + template + abstract_object_pointert initialize_abstract_object( + const typet type, bool top, bool bottom, const exprt &e, + const namespacet &ns); bool has_variables_flag; bool has_structs_flag; bool has_arrays_flag; bool has_pointers_flag; + bool initialized; }; -#endif // VARIABLE_SENSITIVITY_OBJECT_FACTORY_H +/*******************************************************************\ + +Function: variable_sensitivity_object_factoryt::initialize_abstract_object + + Inputs: + abstract_object_classt - the class to use for the abstract object + type - the type of the variable + top - whether the abstract object should be top in the two-value domain + bottom - whether the abstract object should be bottom in the two-value domain + e - if top and bottom are false this expression is used as the starting + pointer for the abstract object + ns - namespace, used when following the input type + + Outputs: An abstract object of the appropriate type. + + Purpose: Initialize the abstract object class and return it. + +\*******************************************************************/ + +template +abstract_object_pointert variable_sensitivity_object_factoryt:: + initialize_abstract_object( + const typet type, + bool top, + bool bottom, + const exprt &e, + const namespacet &ns) +{ + if(top || bottom) + { + return abstract_object_pointert( + new abstract_object_classt(type, top, bottom)); + } + else + { + assert(type==e.type()); + return abstract_object_pointert(new abstract_object_classt(e)); + } +} + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_OBJECT_FACTORY_H // NOLINT(*) From 175e80723aeac9dddccc1350e08a8b4f39ce0dd5 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 20:21:56 +0000 Subject: [PATCH 062/129] Add simplification of the left hand side of assignments. --- regression/goto-analyzer/demo/main.c | 15 ++++++ .../variable_sensitivity_domain.cpp | 47 ++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/regression/goto-analyzer/demo/main.c b/regression/goto-analyzer/demo/main.c index 24e20e280ae..bd125da7e22 100644 --- a/regression/goto-analyzer/demo/main.c +++ b/regression/goto-analyzer/demo/main.c @@ -78,4 +78,19 @@ void func(int unknown) int x = 4; int * xp = &x; int * yp = xp; + + int ** ypp = &yp; + **ypp = *yp; + + int i; + int array[4]; + + i = 0; + array[i] = i; + i = i+1; + array[i] = i; + i = i+1; + array[i] = i; + i = i+1; + array[i] = i; } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 1268facf9e2..6dbd50f5f89 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -10,6 +10,7 @@ Date: April 2016 #include +#include #include "variable_sensitivity_domain.h" @@ -256,7 +257,50 @@ bool variable_sensitivity_domaint::ai_simplify( exprt &condition, const namespacet &ns, const bool lhs) const { if (lhs) - return false; + { + // Care must be taken here to give something that is still writable + if (condition.id()==ID_index) + { + index_exprt ie = to_index_expr(condition); + exprt index = ie.index(); + bool changed = ai_simplify(index, ns, false); + if (changed) + { + ie.index() = index; + condition = simplify_expr(ie, ns); + } + + return changed; + } + else if (condition.id()==ID_dereference) + { + dereference_exprt de = to_dereference_expr(condition); + exprt pointer = de.pointer(); + bool changed = ai_simplify(pointer, ns, false); + if (changed) + { + de.pointer() = pointer; + condition = simplify_expr(de, ns); // So *(&x) -> x + } + + return changed; + } + else if (condition.id()==ID_member) + { + member_exprt me = to_member_expr(condition); + exprt compound = me.compound(); + bool changed = ai_simplify(compound, ns, true); // <-- true! + if (changed) + { + me.compound() = compound; + condition = simplify_expr(me, ns); + } + + return changed; + } + else + return false; + } else { sharing_ptrt res = abstract_state.eval(condition, ns); @@ -271,6 +315,7 @@ bool variable_sensitivity_domaint::ai_simplify( return b; } } + assert(0); // All conditions should be handled } bool variable_sensitivity_domaint::is_bottom() const From dc82227e6496fe189a0d8b8492af59850529b1b7 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 20:37:39 +0000 Subject: [PATCH 063/129] Remove incorrect comment. --- .../variable-sensitivity/variable_sensitivity_domain.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index b26ade5d644..89dbfe1ae5e 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -80,8 +80,7 @@ class variable_sensitivity_domaint : public ai_domain_baset // no states virtual void make_bottom() override; - // all states -- the analysis doesn't use this, - // and domains may refuse to implement it. + // all states virtual void make_top() override; // a reasonable entry-point state From 1209922021b0d24e09a9c04c2b9fa74b47bdffed Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 20:57:37 +0000 Subject: [PATCH 064/129] Review comments and TODOs. --- .../variable-sensitivity/abstract_enviroment.cpp | 12 ++++++++---- .../variable-sensitivity/abstract_object.cpp | 5 +++-- .../variable_sensitivity_domain.cpp | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 4f8a944678c..d37991bfd66 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -33,14 +33,16 @@ Function: abstract_environmentt::eval Outputs: The abstract_object representing the value of the expression - Purpose: Evaluate the value of an expression + Purpose: Evaluate the value of an expression relative to the current domain \*******************************************************************/ abstract_object_pointert abstract_environmentt::eval( const exprt &expr, const namespacet &ns) const { - assert(!is_bottom); + if (is_bottom) + return abstract_object_factory(expr.type(), ns, false, true); + typedef std::function eval_handlert; std::map handlers= { @@ -112,7 +114,7 @@ abstract_object_pointert abstract_environmentt::eval( } }; - // first try to collapse constant folding + // first try to canonicalise, including constant folding const exprt &simplified_expr=simplify_expr(expr, ns); const auto &handler=handlers.find(simplified_expr.id()); @@ -205,6 +207,7 @@ bool abstract_environmentt::assign( } // Write the value for the root symbol back into the map + assert(symbol_expr.type() == final_value->get_type()); if (final_value->is_top()) { map.erase(symbol_expr); @@ -369,6 +372,7 @@ bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) } } + // TODO - split up conjuncts and deal with each part separately // TODO - need a way of converting x==23 into an assign for the value of x return false; @@ -529,7 +533,7 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) Function: abstract_environmentt::havoc Inputs: - havoc_string - debug string to track down havoc causing. + havoc_string - diagnostic string to track down havoc causing. Outputs: None diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 981c893c6c9..79d5d6e85d3 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -267,8 +267,9 @@ Function: abstract_objectt::output Inputs: out - the stream to write to - ai - ? - ns - ? + ai - the abstract interpreter that contains the abstract domain + (that contains the object ... ) + ns - the current namespace Outputs: diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 6dbd50f5f89..d3aadda8eb8 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -306,7 +306,7 @@ bool variable_sensitivity_domaint::ai_simplify( sharing_ptrt res = abstract_state.eval(condition, ns); exprt c = res->to_constant(); - if (c.id() == ID_nil) + if (c.id() == ID_nil) // TODO : simplification within an expression return false; else { From 4cbf595474941bf433f6adf6bd0849064db92b72 Mon Sep 17 00:00:00 2001 From: martin Date: Wed, 1 Mar 2017 13:06:25 +0000 Subject: [PATCH 065/129] Mark unreachable assertions as satisfied. --- .../unreachable_assertions_01/main.c | 28 +++++++++++++++++++ .../unreachable_assertions_01/test.desc | 12 ++++++++ src/goto-analyzer/static_analyzer.cpp | 5 ++++ 3 files changed, 45 insertions(+) create mode 100644 regression/goto-analyzer/unreachable_assertions_01/main.c create mode 100644 regression/goto-analyzer/unreachable_assertions_01/test.desc diff --git a/regression/goto-analyzer/unreachable_assertions_01/main.c b/regression/goto-analyzer/unreachable_assertions_01/main.c new file mode 100644 index 00000000000..53fea7e7493 --- /dev/null +++ b/regression/goto-analyzer/unreachable_assertions_01/main.c @@ -0,0 +1,28 @@ +#include + +int nondet_int (void); + +int main (int argc, char **argv) +{ + int a = 1; + int b = 2; + int x = nondet_int(); + int y = nondet_int(); + + if (a == b) + assert(0); // Trivial false + + if (a == b) + assert(1); // Trivial true + + if (a == b) + assert(x == y); // Undetermined + + if (a == b) + assert(!(x == y) || (x + 1 + a == b + y)); // Non-trivial true + + if (a == b) + assert(!(!(x == y) || (x + 1 + a == b + y))); // Non-trivial false + + return 0; +} diff --git a/regression/goto-analyzer/unreachable_assertions_01/test.desc b/regression/goto-analyzer/unreachable_assertions_01/test.desc new file mode 100644 index 00000000000..1b8a2a4405b --- /dev/null +++ b/regression/goto-analyzer/unreachable_assertions_01/test.desc @@ -0,0 +1,12 @@ +CORE +main.c +--verify --variable +^\[main.assertion.1\] file main.c line 13 function main, assertion 0: Success \(unreachable\)$ +^\[main.assertion.2\] file main.c line 16 function main, assertion 1: Success \(unreachable\)$ +^\[main.assertion.3\] file main.c line 19 function main, assertion x == y: Success \(unreachable\)$ +^\[main.assertion.4\] file main.c line 22 function main, assertion !\(x == y\) || \(x + 1 + a == b + y\): Success \(unreachable\)$ +^\[main.assertion.5\] file main.c line 25 function main, assertion !\(!\(x == y\) || \(x + 1 + a == b + y\)\): Success \(unreachable\)$ +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring diff --git a/src/goto-analyzer/static_analyzer.cpp b/src/goto-analyzer/static_analyzer.cpp index be47933be27..e234a737963 100644 --- a/src/goto-analyzer/static_analyzer.cpp +++ b/src/goto-analyzer/static_analyzer.cpp @@ -118,6 +118,11 @@ void static_analyzert::plain_text_report() result() << "Failure (if reachable)"; fail++; } + else if(domain[i_it].is_bottom()) + { + result() << "Success (unreachable)"; + pass++; + } else { result() << "Unknown"; From d7893d6142aec0b7c53649dc28f69832bf8cd495 Mon Sep 17 00:00:00 2001 From: martin Date: Thu, 2 Mar 2017 20:48:45 +0000 Subject: [PATCH 066/129] Document various of the key ideas behind how goto-analyze works. --- .../abstract_enviroment.cpp | 42 +++++++++++++++++-- .../variable-sensitivity/abstract_object.h | 34 +++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index d37991bfd66..b682257e719 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -150,6 +150,25 @@ Function: abstract_environmentt::assign Purpose: Assign a value to an expression + Assign is in principe simple, it updates the map with the new + abstract object. The challenge is how to handle write to compound + objects, for example: + a[i].x.y = 23; + In this case we clearly want to update a, but we need to delegate to + the object in a so that it updates the right part of it (depending on + what kind of array abstraction it is). So, as we find the variable + ('a' in this case) we build a stack of which part of it is accessed. + + As abstractions may split the assignment into multiple write (for + example pointers that could point to several locations, arrays with + non-constant indexes), each of which has to handle the rest of the + compound write, thus the stack is passed (to write, which does the + actual updating) as an explicit argument rather than just via + recursion. + + The same use case (but for the opposite reason; because you will only + update one of the multiple objects) is also why a merge_write flag is + needed. \*******************************************************************/ bool abstract_environmentt::assign( @@ -352,7 +371,9 @@ Function: abstract_environmentt::assume bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) { // We should only attempt to assume Boolean things - // This should be enforced by the well-structured-ness of the goto-program + // This should be enforced by the well-structured-ness of the + // goto-program and the way assume is used. + assert(expr.type().id()==ID_bool); // Evaluate the expression @@ -372,8 +393,23 @@ bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) } } - // TODO - split up conjuncts and deal with each part separately - // TODO - need a way of converting x==23 into an assign for the value of x + /* TODO : full implementation here + * Note that this is *very* syntax dependent so some normalisation would help + * 1. split up conjucts, handle each part separately + * 2. check how many variables the term contains + * 0 = this should have been simplified away + * 2+ = ignore as this is a non-relational domain + * 1 = extract the expression for the variable, + * care must be taken for things like a[i] + * which can be used if i can be resolved to a constant + * 3. use abstract_object_factory to build an abstract_objectt + * of the correct type (requires a little extension) + * This allows constant domains to handle x==23, + * intervals to handle x < 4, etc. + * 4. eval the current value of the variable + * 5. compute the meet (not merge!) of the two abstract_objectt's + * 6. assign the new value back to the environment. + */ return false; } diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index e6668ad5064..dd8f4acb680 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -4,6 +4,22 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com + abstract_objectt is the top of the inheritance heirarchy of objects + used to represent individual variables in the general non-relational + domain. It is a two element abstraction (i.e. it is either top or + bottom). Within the hierachy of objects under it, child classes are + more precise abstractions (the converse doesn't hold to avoid + diamonds and inheriting unnecessary fields). Thus the common parent + of two classes is an abstraction capable of representing both. This + is important for understanding merge. + + These objects are intended to be used in a copy-on-write style, which + is why their interface differs a bit from ai_domain_baset's + modify-in-place style of interface. + + Although these can represent bottom (this variable cannot take any + value) it is not common for them to do so. + \*******************************************************************/ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H @@ -54,6 +70,24 @@ class namespacet; } \ } \ +/* Merge is designed to allow different abstractions to be merged + * gracefully. There are two real use-cases for this: + * + * 1. Having different abstractions for the variable in different + * parts of the program. + * 2. Allowing different domains to write to ambiguous locations + * for example, if a stores multiple values (maybe one per + * location) with a constant for each, i does not represent one + * single value (top, non-unit interval, etc.) and v is something + * other than constant, then + * a[i] = v + * will cause this to happen. + * + * To handle this, merge finds the most specific class that is a + * parent to both classes and generates a new object of that type. + * The actual state is then merged by merge_state. + */ + template using sharing_ptrt=std::shared_ptr; From b6e03bd03962970e314b6354e82f6c12fb3bc85e Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 6 Mar 2017 19:41:13 +0000 Subject: [PATCH 067/129] Renamed methods to provide a more consistent interface Converted `get_is_...` to `is_...` be consistent with the interface of ai_base_domaint. Converted `get_type` to `type` to be more consistent with exprt. --- .../abstract_enviroment.cpp | 28 +++++++++--------- .../abstract_enviroment.h | 6 ++-- .../variable-sensitivity/abstract_object.cpp | 26 ++++++++++++----- .../variable-sensitivity/abstract_object.h | 6 ++-- .../array_abstract_object.cpp | 2 +- .../constant_pointer_abstract_object.cpp | 8 ++--- .../pointer_abstract_object.cpp | 2 +- .../variable_sensitivity_domain.cpp | 29 +++++++++++++++++-- 8 files changed, 72 insertions(+), 35 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index b682257e719..7655d4c33a3 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -40,7 +40,7 @@ Function: abstract_environmentt::eval abstract_object_pointert abstract_environmentt::eval( const exprt &expr, const namespacet &ns) const { - if (is_bottom) + if (bottom) return abstract_object_factory(expr.type(), ns, false, true); typedef std::function eval_handlert; @@ -226,7 +226,7 @@ bool abstract_environmentt::assign( } // Write the value for the root symbol back into the map - assert(symbol_expr.type() == final_value->get_type()); + assert(symbol_expr.type() == final_value->type()); if (final_value->is_top()) { map.erase(symbol_expr); @@ -387,7 +387,7 @@ bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) if (possibly_constant.is_false()) { - bool currently_bottom = get_is_bottom(); + bool currently_bottom = is_bottom(); make_bottom(); return !currently_bottom; } @@ -508,12 +508,12 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) - if(is_bottom) + if(bottom) { *this=env; - return !env.is_bottom; + return !env.bottom; } - else if(env.is_bottom) + else if(env.bottom) { return false; } @@ -599,7 +599,7 @@ void abstract_environmentt::make_top() { // since we assume anything is not in the map is top this is sufficient map.clear(); - is_bottom=false; + bottom=false; } /*******************************************************************\ @@ -617,12 +617,12 @@ Function: abstract_environmentt::make_bottom void abstract_environmentt::make_bottom() { map.clear(); - is_bottom=true; + bottom=true; } /*******************************************************************\ -Function: abstract_environmentt::get_is_bottom +Function: abstract_environmentt::is_bottom Inputs: @@ -632,14 +632,14 @@ Function: abstract_environmentt::get_is_bottom \*******************************************************************/ -bool abstract_environmentt::get_is_bottom() const +bool abstract_environmentt::is_bottom() const { - return map.empty() && is_bottom; + return map.empty() && bottom; } /*******************************************************************\ -Function: abstract_environmentt::get_is_top +Function: abstract_environmentt::is_top Inputs: @@ -649,9 +649,9 @@ Function: abstract_environmentt::get_is_top \*******************************************************************/ -bool abstract_environmentt::get_is_top() const +bool abstract_environmentt::is_top() const { - return map.empty() && !is_bottom; + return map.empty() && !bottom; } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 4b65aeab3ec..32904e2bc1a 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -57,14 +57,14 @@ class abstract_environmentt void make_top(); void make_bottom(); - bool get_is_bottom() const; - bool get_is_top() const; + bool is_bottom() const; + bool is_top() const; void output( std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; protected: - bool is_bottom; + bool bottom; // We may need to break out more of these cases into these virtual abstract_object_pointert eval_expression( diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 79d5d6e85d3..06265942d4b 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -32,7 +32,7 @@ Function: abstract_objectt::abstract_objectt \*******************************************************************/ abstract_objectt::abstract_objectt(const typet &type): -type(type), top(true), bottom(false) +t(type), top(true), bottom(false) {} /*******************************************************************\ @@ -52,7 +52,7 @@ Function: abstract_objectt::abstract_objectt \*******************************************************************/ abstract_objectt::abstract_objectt(const typet &type, bool top, bool bottom): - type(type), top(top), bottom(bottom) + t(type), top(top), bottom(bottom) { assert(!(top && bottom)); } @@ -71,7 +71,7 @@ Function: abstract_objectt::abstract_objectt \*******************************************************************/ abstract_objectt::abstract_objectt(const abstract_objectt &old): - type(old.type), top(old.top), bottom(old.bottom) + t(old.t), top(old.top), bottom(old.bottom) {} /*******************************************************************\ @@ -88,12 +88,24 @@ Function: abstract_objectt::abstract_objectt \*******************************************************************/ abstract_objectt::abstract_objectt(const exprt &expr): -type(expr.type()), top(true), bottom(false) +t(expr.type()), top(true), bottom(false) {} -const typet &abstract_objectt::get_type() const +/*******************************************************************\ + +Function: abstract_objectt::type + + Inputs: + + Outputs: The program type this abstract object represents + + Purpose: Get the real type of the variable this abstract object is + representing. + +\*******************************************************************/ +const typet &abstract_objectt::type() const { - return type; + return t; } /*******************************************************************\ @@ -139,7 +151,7 @@ Function: abstract_objectt::merge abstract_object_pointert abstract_objectt::merge( const abstract_object_pointert op, bool &out_any_modifications) { - assert(type==op->type); + assert(t==op->t); abstract_object_pointert m=abstract_object_pointert(new abstract_objectt(*this)); out_any_modifications=m->merge_state(abstract_object_pointert(this), op); return m; diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index dd8f4acb680..f5bc6dd0f6b 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -46,7 +46,7 @@ class namespacet; const abstract_object_pointert op, \ bool &out_any_modifications) \ {\ - assert(type==op->get_type()); \ + assert(type()==op->type()); \ typedef std::remove_const::type \ >::type current_typet; \ \ @@ -101,7 +101,7 @@ class abstract_objectt abstract_objectt(const abstract_objectt &old); abstract_objectt(const exprt &expr); - const typet &get_type() const; + const typet &type() const; virtual bool is_top() const; virtual bool is_bottom() const; @@ -128,7 +128,7 @@ class abstract_objectt CLONE protected: - typet type; + typet t; bool top; bool bottom; }; diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 13cc0cb9e55..1bd5b79cc59 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -111,7 +111,7 @@ abstract_object_pointert array_abstract_objectt::read_index( const index_exprt &index, const namespacet& ns) const { - array_typet array_type(to_array_type(type)); + array_typet array_type(to_array_type(type())); const typet &subtype=array_type.subtype(); // if we are bottom then so are the values in the array diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index b7f023f2f41..9fac5694c07 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -274,7 +274,7 @@ abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( // Return top if dereferencing a null pointer or we are top bool is_value_top = top || value.id()==ID_nil; return env.abstract_object_factory( - type.subtype(), ns, is_value_top, !is_value_top); + type().subtype(), ns, is_value_top, !is_value_top); } else { @@ -285,11 +285,11 @@ abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( else if(value.id()==ID_constant) { // Reading a null pointer, return top - return env.abstract_object_factory(type.subtype(), ns, true, false); + return env.abstract_object_factory(type().subtype(), ns, true, false); } else { - return env.abstract_object_factory(type.subtype(), ns, true, false); + return env.abstract_object_factory(type().subtype(), ns, true, false); } } } @@ -350,7 +350,7 @@ sharing_ptrt if(stack.empty()) { // We should not be changing the type of an abstract object - assert(new_value->get_type()==type.subtype()); + assert(new_value->type()==type().subtype()); if(merging_write) diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index 448623583f8..c1c05082480 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -110,7 +110,7 @@ Function: pointer_abstract_objectt::read_dereference abstract_object_pointert pointer_abstract_objectt::read_dereference( const abstract_environmentt &env, const namespacet &ns) const { - pointer_typet pointer_type(to_pointer_type(type)); + pointer_typet pointer_type(to_pointer_type(type())); const typet &pointed_to_type=pointer_type.subtype(); return env.abstract_object_factory(pointed_to_type, ns, true, false); diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index d3aadda8eb8..692e3e06211 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -318,12 +318,37 @@ bool variable_sensitivity_domaint::ai_simplify( assert(0); // All conditions should be handled } +/*******************************************************************\ + +Function: variable_sensitivity_domaint::is_bottom + + Inputs: + + Outputs: True if the domain is bottom (i.e. unreachable). + + Purpose: Find out if the domain is currently unreachable. + +\*******************************************************************/ + bool variable_sensitivity_domaint::is_bottom() const { - return abstract_state.get_is_bottom(); + return abstract_state.is_bottom(); } +/*******************************************************************\ + +Function: variable_sensitivity_domaint::is_top + + Inputs: + + Outputs: True if the domain is top + + Purpose: Is the domain completely top at this state + +\*******************************************************************/ bool variable_sensitivity_domaint::is_top() const { - return abstract_state.get_is_top(); + return abstract_state.is_top(); } + + From e6064b6f4a1cfb221f34953f7283b8b022922935 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 6 Mar 2017 20:38:46 +0000 Subject: [PATCH 068/129] Protect top and bottom as much as possible. To help enforce copy-on-write, member variables added by the abstraction heirarchy should be private where possible and accessed by const only functions. --- .../variable-sensitivity/abstract_object.cpp | 8 ++++---- .../variable-sensitivity/abstract_object.h | 8 ++++++-- .../array_abstract_object.cpp | 7 ++----- .../constant_abstract_value.cpp | 18 ++++++++---------- .../constant_pointer_abstract_object.cpp | 18 +++++++++--------- .../pointer_abstract_object.cpp | 7 ++----- .../struct_abstract_object.cpp | 7 ++----- 7 files changed, 33 insertions(+), 40 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 06265942d4b..d38f0ca9593 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -32,7 +32,7 @@ Function: abstract_objectt::abstract_objectt \*******************************************************************/ abstract_objectt::abstract_objectt(const typet &type): -t(type), top(true), bottom(false) +t(type), bottom(false), top(true) {} /*******************************************************************\ @@ -52,7 +52,7 @@ Function: abstract_objectt::abstract_objectt \*******************************************************************/ abstract_objectt::abstract_objectt(const typet &type, bool top, bool bottom): - t(type), top(top), bottom(bottom) + t(type), bottom(bottom), top(top) { assert(!(top && bottom)); } @@ -71,7 +71,7 @@ Function: abstract_objectt::abstract_objectt \*******************************************************************/ abstract_objectt::abstract_objectt(const abstract_objectt &old): - t(old.t), top(old.top), bottom(old.bottom) + t(old.t), bottom(old.bottom), top(old.top) {} /*******************************************************************\ @@ -88,7 +88,7 @@ Function: abstract_objectt::abstract_objectt \*******************************************************************/ abstract_objectt::abstract_objectt(const exprt &expr): -t(expr.type()), top(true), bottom(false) +t(expr.type()), bottom(false), top(true) {} /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index f5bc6dd0f6b..57035649782 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -127,10 +127,14 @@ class abstract_objectt CLONE -protected: +private: // To enforce copy-on-write these are private and have read-only accessors typet t; - bool top; bool bottom; +protected: // TODO - remove + bool top; + +protected: // The one exception is merge_state in descendent classes, which needs this + void make_top() { top=true; } }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 1bd5b79cc59..e530bb6bfaf 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -158,10 +158,7 @@ sharing_ptrt array_abstract_objectt::write_index( } else { - sharing_ptrt copy( - new array_abstract_objectt(*this)); - copy->top=false; - copy->bottom=true; - return copy; + return sharing_ptrt( + new array_abstract_objectt(type(), false, true)); } } diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index 011c4749df7..f05102498e0 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -23,14 +23,12 @@ constant_abstract_valuet::constant_abstract_valuet( {} constant_abstract_valuet::constant_abstract_valuet(const exprt e): - abstract_valuet(e), value(e) -{ - top=false; -} + abstract_valuet(e.type(), false, false), value(e) +{} exprt constant_abstract_valuet::to_constant() const { - if(!top && !bottom) + if(!is_top() && !is_bottom()) { return this->value; } @@ -43,7 +41,7 @@ exprt constant_abstract_valuet::to_constant() const void constant_abstract_valuet::output( std::ostream &out, const ai_baset &ai, const namespacet &ns) { - if(!top && !bottom) + if(!is_top() && !is_bottom()) { out << to_constant_expr(value).get_value(); } @@ -58,7 +56,7 @@ bool constant_abstract_valuet::merge_state( constant_abstract_value_pointert op2) { bool parent_merge_change=abstract_objectt::merge_state(op1, op2); - if (!top && !bottom) + if (!is_top() && !is_bottom()) { if (op1->value==op2->value) { @@ -67,11 +65,11 @@ bool constant_abstract_valuet::merge_state( } else // values different { - top=true; - assert(bottom==false); + make_top(); + assert(is_bottom()==false); // Clear out the expression value=exprt(); - return !op1->top; + return !op1->is_top(); } } else // either top or bottom diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 9fac5694c07..7a4265bb0ad 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -148,7 +148,7 @@ bool constant_pointer_abstract_objectt::merge_state( const constant_pointer_abstract_pointert op2) { bool parent_merge_change=abstract_objectt::merge_state(op1, op2); - if(top || bottom) + if(is_top() || is_bottom()) { return parent_merge_change; } @@ -161,10 +161,10 @@ bool constant_pointer_abstract_objectt::merge_state( } else { - top=true; + make_top(); value=nil_exprt(); - assert(!bottom); - return !op1->top; + assert(!is_bottom()); + return !op1->is_top(); } } } @@ -188,7 +188,7 @@ Function: constant_pointer_abstract_objectt::to_constant exprt constant_pointer_abstract_objectt::to_constant() const { - if(top || bottom) + if(is_top() || is_bottom()) { return pointer_abstract_objectt::to_constant(); } @@ -219,7 +219,7 @@ Function: constant_pointer_abstract_objectt::output void constant_pointer_abstract_objectt::output( std::ostream &out, const ai_baset &ai, const namespacet &ns) { - if(top || bottom) + if(is_top() || is_bottom()) { pointer_abstract_objectt::output(out, ai, ns); } @@ -269,10 +269,10 @@ Function: constant_pointer_abstract_objectt::read_dereference abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( const abstract_environmentt &env, const namespacet &ns) const { - if(top || bottom || value.id()==ID_nil) + if(is_top() || is_bottom() || value.id()==ID_nil) { // Return top if dereferencing a null pointer or we are top - bool is_value_top = top || value.id()==ID_nil; + bool is_value_top = is_top() || value.id()==ID_nil; return env.abstract_object_factory( type().subtype(), ns, is_value_top, !is_value_top); } @@ -327,7 +327,7 @@ sharing_ptrt const abstract_object_pointert new_value, bool merging_write) { - if(top || bottom) + if(is_top() || is_bottom()) { return pointer_abstract_objectt::write_dereference( environment, ns, stack, new_value, merging_write); diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index c1c05082480..3507e6e40bd 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -156,10 +156,7 @@ sharing_ptrt } else { - sharing_ptrt copy( - new pointer_abstract_objectt(*this)); - copy->top=false; - copy->bottom=true; - return copy; + return sharing_ptrt( + new pointer_abstract_objectt(type(), false, true)); } } diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index 4ebe07d440d..13264c5cbc5 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -155,10 +155,7 @@ sharing_ptrt struct_abstract_objectt::write_component( } else { - sharing_ptrt copy( - new struct_abstract_objectt(*this)); - copy->top=false; - copy->bottom=true; - return copy; + return sharing_ptrt( + new struct_abstract_objectt(type(), false, true)); } } From d17f3a71b8370a0ecaeb6ab9d1e647a8d529cb31 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 6 Mar 2017 20:50:47 +0000 Subject: [PATCH 069/129] Output should be const-clean. --- src/analyses/variable-sensitivity/abstract_object.cpp | 2 +- src/analyses/variable-sensitivity/abstract_object.h | 2 +- src/analyses/variable-sensitivity/constant_abstract_value.cpp | 2 +- src/analyses/variable-sensitivity/constant_abstract_value.h | 2 +- .../variable-sensitivity/constant_pointer_abstract_object.cpp | 2 +- .../variable-sensitivity/constant_pointer_abstract_object.h | 3 ++- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index d38f0ca9593..def354b411d 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -290,7 +290,7 @@ Function: abstract_objectt::output \*******************************************************************/ void abstract_objectt::output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) + std::ostream &out, const ai_baset &ai, const namespacet &ns) const { if(top) { diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 57035649782..dd58f110f1f 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -123,7 +123,7 @@ class abstract_objectt virtual exprt to_constant() const; virtual void output( - std::ostream &out, const class ai_baset &ai, const namespacet &ns); + std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; CLONE diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index f05102498e0..a01124faa19 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -39,7 +39,7 @@ exprt constant_abstract_valuet::to_constant() const } void constant_abstract_valuet::output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) + std::ostream &out, const ai_baset &ai, const namespacet &ns) const { if(!is_top() && !is_bottom()) { diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 410e41cf7e8..75123e01550 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -31,7 +31,7 @@ class constant_abstract_valuet : public abstract_valuet virtual void output( std::ostream &out, const class ai_baset &ai, - const class namespacet &ns); + const class namespacet &ns) const; protected : bool merge_state( diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 7a4265bb0ad..e8b60f3551a 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -217,7 +217,7 @@ Function: constant_pointer_abstract_objectt::output \*******************************************************************/ void constant_pointer_abstract_objectt::output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) + std::ostream &out, const ai_baset &ai, const namespacet &ns) const { if(is_top() || is_bottom()) { diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 44e996d6c3d..60f54f39389 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -36,7 +36,8 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt const constant_pointer_abstract_pointert op2); exprt to_constant() const; - void output(std::ostream &out, const ai_baset &ai, const namespacet &ns); + void output( + std::ostream &out, const ai_baset &ai, const namespacet &ns) const; abstract_object_pointert read_dereference( const abstract_environmentt &env, const namespacet &ns) const; From 90fcdc9fc3f1dea4ab2b260eb3249d4d1f58ae6d Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Mon, 27 Feb 2017 18:39:47 +0000 Subject: [PATCH 070/129] Implementing sensitive struct abstract object Added structs to object factory. Added debug output disabled debug output, added structs to demo --- regression/goto-analyzer/demo/main.c | 12 + src/analyses/Makefile | 1 + .../abstract_enviroment.cpp | 9 +- .../abstract_enviroment.h | 1 - .../full_struct_abstract_object.cpp | 358 ++++++++++++++++++ .../full_struct_abstract_object.h | 57 +++ .../struct_abstract_object.cpp | 5 +- .../struct_abstract_object.h | 10 +- .../variable_sensitivity_object_factory.cpp | 4 +- .../variable_sensitivity_object_factory.h | 1 + 10 files changed, 448 insertions(+), 10 deletions(-) create mode 100644 src/analyses/variable-sensitivity/full_struct_abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/full_struct_abstract_object.h diff --git a/regression/goto-analyzer/demo/main.c b/regression/goto-analyzer/demo/main.c index bd125da7e22..f9120ad7f96 100644 --- a/regression/goto-analyzer/demo/main.c +++ b/regression/goto-analyzer/demo/main.c @@ -93,4 +93,16 @@ void func(int unknown) array[i] = i; i = i+1; array[i] = i; + + typedef struct + { + int a; + int b; + } struct_t; + + struct_t s; + s.a = 1; + + assert(s.a == 1); + assert(s.a == 2); } diff --git a/src/analyses/Makefile b/src/analyses/Makefile index 0f3595b5e34..520987b2d40 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -34,6 +34,7 @@ SRC = ai.cpp \ variable-sensitivity/struct_abstract_object.cpp \ variable-sensitivity/variable_sensitivity_domain.cpp \ variable-sensitivity/variable_sensitivity_object_factory.cpp \ + variable-sensitivity/full_struct_abstract_object.cpp # Empty last line INCLUDES= -I .. diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 7655d4c33a3..6dbf166e332 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -6,6 +6,7 @@ \*******************************************************************/ #include "abstract_enviroment.h" + #include #include #include @@ -20,6 +21,7 @@ #include + #ifdef DEBUG #include #endif @@ -72,6 +74,7 @@ abstract_object_pointert abstract_environmentt::eval( ID_member, [&](const exprt &expr) { member_exprt member_expr(to_member_expr(expr)); + sharing_ptrt struct_abstract_object= std::dynamic_pointer_cast( eval(member_expr.compound(), ns)); @@ -225,8 +228,11 @@ bool abstract_environmentt::assign( final_value=value; } + const typet &lhs_type=ns.follow(symbol_expr.type()); + const typet &rhs_type=ns.follow(final_value->type()); + // Write the value for the root symbol back into the map - assert(symbol_expr.type() == final_value->type()); + assert(lhs_type==rhs_type); if (final_value->is_top()) { map.erase(symbol_expr); @@ -321,6 +327,7 @@ abstract_object_pointert abstract_environmentt::write( sharing_ptrt modified_struct= struct_abstract_object->write_component( *this, + ns, stack, to_member_expr(next_expr), rhs_object, diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 32904e2bc1a..227a8455c87 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -46,7 +46,6 @@ class abstract_environmentt virtual abstract_object_pointert abstract_object_factory( const typet &type, const exprt &e, const namespacet &ns) const; - virtual bool merge(const abstract_environmentt &env); // This should be used as a default case / everything else has failed diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp new file mode 100644 index 00000000000..8fec8896a46 --- /dev/null +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -0,0 +1,358 @@ +/*******************************************************************\ + +Module: Struct abstract object + +Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ + +#include +#include +#include + +#include "full_struct_abstract_object.h" + +// #define DEBUG + +#ifdef DEBUG +#include +#endif + +/*******************************************************************\ + +Function: full_struct_abstract_objectt::struct_abstract_objectt + + Inputs: + type - the type the abstract_object is representing + + Outputs: + + Purpose: + +\*******************************************************************/ + +full_struct_abstract_objectt::full_struct_abstract_objectt(const typet &t): + struct_abstract_objectt(t) +{ + assert(t.id()==ID_struct); +} + +/*******************************************************************\ + +Function: struct_abstract_objectt::struct_abstract_objectt + + Inputs: + type - the type the abstract_object is representing + top - is the abstract_object starting as top + bottom - is the abstract_object starting as bottom + + Outputs: + + Purpose: Start the abstract object at either top or bottom or + neither asserts if both top and bottom are true + +\*******************************************************************/ + +full_struct_abstract_objectt::full_struct_abstract_objectt( + const typet &t, bool top, bool bottom): + struct_abstract_objectt(t, top, bottom) +{ + assert(t.id()==ID_struct); +} + +/*******************************************************************\ + +Function: full_struct_abstract_objectt::full_struct_abstract_objectt + + Inputs: + old - the abstract object to copy from + + Outputs: + + Purpose: + +\*******************************************************************/ + +full_struct_abstract_objectt::full_struct_abstract_objectt( + const full_struct_abstract_objectt &old): + struct_abstract_objectt(old) +{ + +} + +/*******************************************************************\ + +Function: full_struct_abstract_objectt::full_struct_abstract_objectt + + Inputs: + expr - the expression to use as the starting pointer for an + abstract object + + Outputs: + + Purpose: + +\*******************************************************************/ + +full_struct_abstract_objectt::full_struct_abstract_objectt(const exprt &e): + struct_abstract_objectt(e) +{ + assert(e.type().id()==ID_struct); +} + +/*******************************************************************\ + +Function: struct_abstract_objectt::read_component + + Inputs: + environment - the abstract environment + member_expr - the expression uses to access a specific component + + Outputs: The abstract object representing the value of that + component. For this abstraction this will always be top + since we are not tracking the struct. + + Purpose: A helper function to evaluate the abstract object contained + within a struct. More precise abstractions may override + this to return more precise results. + +\*******************************************************************/ + +abstract_object_pointert full_struct_abstract_objectt::read_component( + const abstract_environmentt &environment, + const member_exprt &member_expr, + const namespacet& ns) +{ +#ifdef DEBUG + std::cout << "Reading component " << member_expr.get_component_name() + << std::endl; +#endif + + if(is_top()) + { + return environment.abstract_object_factory( + member_expr.type(), ns, true); + } + else + { + assert(!is_bottom()); + + irep_idt c=member_expr.get_component_name(); + + struct_mapt::const_iterator it=map.find(c); + + if(it!=map.cend()) + { + return it->second; + } + else + { + return environment.abstract_object_factory( + member_expr.type(), ns, true); + } + } +} + +/*******************************************************************\ + +Function: struct_abstract_objectt::write_component + + Inputs: + environment - the abstract environment + stack - the remaining stack of expressions on the LHS to evaluate + member_expr - the expression uses to access a specific component + value - the value we are trying to write to the component + + Outputs: The struct_abstract_objectt representing the result of + writing to a specific component. In this case this will + always be top as we are not tracking the value of this + struct. + + Purpose: A helper function to evaluate writing to a component of a + struct. More precise abstractions may override this to + update what they are storing for a specific component. + +\*******************************************************************/ + +sharing_ptrt full_struct_abstract_objectt::write_component( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack &stack, + const member_exprt &member_expr, + const abstract_object_pointert value, + bool merging_write) +{ +#ifdef DEBUG + std::cout << "Writing component " << member_expr.get_component_name() + << std::endl; +#endif + + if(is_bottom()) + { + return sharing_ptrt( + new full_struct_abstract_objectt( + member_expr.compound().type(), false, true)); + } + + // we only handle one level currently + if(!stack.empty()) + { + sharing_ptrt copy( + new full_struct_abstract_objectt(*this)); + + irep_idt c=member_expr.get_component_name(); + copy->map[c]= + environment.write(copy->map[c], value, stack, ns, merging_write); + + return copy; + } + else + { + sharing_ptrt copy( + new full_struct_abstract_objectt(*this)); + +#ifdef DEBUG + std::cout << "Setting component" << std::endl; +#endif + + irep_idt c=member_expr.get_component_name(); + + if(merging_write) + { + if(is_top()) // struct is top + return copy; + + assert(!copy->map.empty()); + + struct_mapt &m=copy->map; + + struct_mapt::iterator it=m.find(c); + + if(it==m.end()) // component is top + return copy; + + bool dummy; + + it->second=it->second->merge(value, dummy); + } + else + { + copy->map[c]=value; + + copy->top=false; + assert(!copy->is_bottom()); + } + + return copy; + } +} + +/*******************************************************************\ + +Function: full_struct_abstract_objectt::merge_state + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +bool full_struct_abstract_objectt::merge_state( + const sharing_ptrt op1, + const sharing_ptrt op2) +{ + bool changed; + + // consider top and bottom in parent + changed=abstract_objectt::merge_state(op1, op2); + + if(is_top() || is_bottom()) + { + map.clear(); + return changed; + } + + assert(!op1->is_top() && !op2->is_top()); + assert(!op1->is_bottom() && !op2->is_bottom()); + + if(op2->is_bottom()) + return false; + + if(op1->is_bottom()) + { + map=op2->map; + return true; + } + + // at this point both are different from top and bottom + + const struct_mapt &m1=op1->map; + const struct_mapt &m2=op2->map; + + assert(!m1.empty()); + assert(!m2.empty()); + + map.clear(); + + struct_mapt::const_iterator it1=m1.begin(); + struct_mapt::const_iterator it2=m2.begin(); + + bool modified=false; + + while(true) + { + if(it1->firstfirst) + { + // element of m1 is not in m2 + + it1++; + modified=true; + if(it1==m1.end()) + break; + } + else if(it2->firstfirst) + { + // element of m2 is not in m1 + + it2++; + if(it2==m2.end()) + { + modified=true; // as there is a remaining element in m1 + break; + } + } + else + { + // merge entries + + const abstract_object_pointert &v1=it1->second; + const abstract_object_pointert &v2=it2->second; + + bool changes=false; + abstract_object_pointert v_new; + + v_new=v1->merge(v2, changes); + + modified|=changes; + + map[it1->first]=v_new; + + it1++; + + if(it1==m1.end()) + break; + + it2++; + + if(it2==m2.end()) + { + modified=true; // as there is a remaining element in m1 + break; + } + } + } + + return modified; +} diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h new file mode 100644 index 00000000000..00bfe843d7f --- /dev/null +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -0,0 +1,57 @@ +/*******************************************************************\ + +Module: Struct abstract object + +Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ + +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ONE_LEVEL_STRUCT_ABSTRACT_OBJECT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ONE_LEVEL_STRUCT_ABSTRACT_OBJECT_H + +#include +#include +#include + +class abstract_environmentt; +class member_exprt; + +class full_struct_abstract_objectt:public struct_abstract_objectt +{ +public: + explicit full_struct_abstract_objectt(const typet &type); + + full_struct_abstract_objectt(const typet &type, bool top, bool bottom); + + explicit full_struct_abstract_objectt(const full_struct_abstract_objectt &old); + explicit full_struct_abstract_objectt(const exprt &expr); + + CLONE + MERGE(struct_abstract_objectt) + + // Set the state of this to the merge result of op1 and op2 and + // return if the result is different from op1 + bool merge_state( + const sharing_ptrt op1, + const sharing_ptrt op2); + + // struct interface + virtual abstract_object_pointert read_component( + const abstract_environmentt &environment, + const member_exprt &member_expr, + const namespacet& ns) override; + + virtual sharing_ptrt write_component( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack &stack, + const member_exprt &member_expr, + const abstract_object_pointert value, + bool merging_write) override; + + // no entry means component is top + typedef std::map struct_mapt; + struct_mapt map; +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ONE_LEVEL_STRUCT_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index 13264c5cbc5..238fb88c531 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -142,8 +142,9 @@ Function: struct_abstract_objectt::write_component \*******************************************************************/ sharing_ptrt struct_abstract_objectt::write_component( - const abstract_environmentt &environment, - const std::stack stack, + abstract_environmentt &environment, + const namespacet &ns, + const std::stack &stack, const member_exprt &member_expr, const abstract_object_pointert value, bool merging_write) diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index 9b9cb55d0b6..44920e76cb6 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -30,13 +30,15 @@ class struct_abstract_objectt:public abstract_objectt virtual abstract_object_pointert read_component( const abstract_environmentt &environment, const member_exprt &member_expr, - const namespacet& ns); + const namespacet &ns); virtual sharing_ptrt write_component( - const abstract_environmentt &environment, - const std::stack stack, + abstract_environmentt &environment, + const namespacet &ns, + const std::stack &stack, const member_exprt &member_expr, - const abstract_object_pointert value, bool merging_write); + const abstract_object_pointert value, + bool merging_write); }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index fb034763ef1..642d7eefbdd 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -107,13 +107,13 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: return initialize_abstract_object( followed_type, top, bottom, e, ns); case POINTER_SENSITIVE: - return initialize_abstract_object( + return initialize_abstract_object( followed_type, top, bottom, e, ns); case POINTER_INSENSITIVE: return initialize_abstract_object( followed_type, top, bottom, e, ns); case STRUCT_SENSITIVE: - return initialize_abstract_object( + return initialize_abstract_object( followed_type, top, bottom, e, ns); case STRUCT_INSENSITIVE: return initialize_abstract_object( diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index 21346d01413..9eddb8e6b3b 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -13,6 +13,7 @@ #include #include #include +#include #include From cd536372668233759de6a2560dc9ac2f72af23e4 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 6 Mar 2017 18:21:46 +0000 Subject: [PATCH 071/129] If anything is assigned the value bottom, the whole domain should be set to bottom. --- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 6dbf166e332..6ff6dd446bb 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -179,6 +179,13 @@ bool abstract_environmentt::assign( { assert(value); + if(value->is_bottom()) + { + bool bottom_at_start=this->is_bottom(); + this->make_bottom(); + return !bottom_at_start; + } + // Build a stack of index, member and dereference accesses which // we will work through the relevant abstract objects exprt s = expr; From 96eef7dad628aadd9cae6fae54dfd8f7f393ab49 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 6 Mar 2017 19:25:15 +0000 Subject: [PATCH 072/129] A missing case in the factory code means that constant assertions were not being handled correctly. This means all the sensitivity tests for primitive types now pass. --- .../goto-analyzer/constant_assertions_01/main.c | 17 +++++++++++++++++ .../constant_assertions_01/test.desc | 12 ++++++++++++ .../goto-analyzer/constant_assertions_02/main.c | 17 +++++++++++++++++ .../constant_assertions_02/test.desc | 12 ++++++++++++ .../sensitivity-test-constants-int/test.desc | 2 +- .../variable_sensitivity_object_factory.cpp | 2 +- 6 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 regression/goto-analyzer/constant_assertions_01/main.c create mode 100644 regression/goto-analyzer/constant_assertions_01/test.desc create mode 100644 regression/goto-analyzer/constant_assertions_02/main.c create mode 100644 regression/goto-analyzer/constant_assertions_02/test.desc diff --git a/regression/goto-analyzer/constant_assertions_01/main.c b/regression/goto-analyzer/constant_assertions_01/main.c new file mode 100644 index 00000000000..6cc8b8a6054 --- /dev/null +++ b/regression/goto-analyzer/constant_assertions_01/main.c @@ -0,0 +1,17 @@ +#include + +int nondet_int (void); + +int main (int argc, char **argv) +{ + int x = nondet_int(); + int y = nondet_int(); + + assert(0); + assert(0 && 1); + assert(0 || 0); + assert(0 && x); + assert(y && 0); + + return 0; +} diff --git a/regression/goto-analyzer/constant_assertions_01/test.desc b/regression/goto-analyzer/constant_assertions_01/test.desc new file mode 100644 index 00000000000..f01bcf15bba --- /dev/null +++ b/regression/goto-analyzer/constant_assertions_01/test.desc @@ -0,0 +1,12 @@ +CORE +main.c +--verify --variable +^\[main.assertion.1\] file main.c .* assertion 0: Failure \(if reachable\)$ +^\[main.assertion.2\] file main.c .* assertion 0 && 1: Failure \(if reachable\)$ +^\[main.assertion.3\] file main.c .* assertion 0 || 0: Failure \(if reachable\)$ +^\[main.assertion.4\] file main.c .* assertion 0 && x: Failure \(if reachable\)$ +^\[main.assertion.5\] file main.c .* assertion y && 0: Failure \(if reachable\)$ +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_assertions_02/main.c b/regression/goto-analyzer/constant_assertions_02/main.c new file mode 100644 index 00000000000..e937622ad2b --- /dev/null +++ b/regression/goto-analyzer/constant_assertions_02/main.c @@ -0,0 +1,17 @@ +#include + +int nondet_int (void); + +int main (int argc, char **argv) +{ + int x = nondet_int(); + int y = nondet_int(); + + assert(1); + assert(0 || 1); + assert(1 && 1); + assert(1 || x); + assert(y || 1); + + return 0; +} diff --git a/regression/goto-analyzer/constant_assertions_02/test.desc b/regression/goto-analyzer/constant_assertions_02/test.desc new file mode 100644 index 00000000000..b5fad36b1ad --- /dev/null +++ b/regression/goto-analyzer/constant_assertions_02/test.desc @@ -0,0 +1,12 @@ +CORE +main.c +--verify --variable +^\[main\.assertion\.1\] file main\.c .* assertion 1: Success +^\[main\.assertion\.2\] file main\.c .* assertion 0 || 1: Success +^\[main\.assertion\.3\] file main\.c .* assertion 1 && 1: Success +^\[main\.assertion\.4\] file main\.c .* assertion 1 || x: Success +^\[main\.assertion\.5\] file main\.c .* assertion y || 1: Success +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-int/test.desc b/regression/goto-analyzer/sensitivity-test-constants-int/test.desc index d3c274a9447..20156736ef1 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-int/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-int/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_int.c --variable --verify ^EXIT=0$ diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 642d7eefbdd..906de5958bf 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -32,7 +32,7 @@ variable_sensitivity_object_factoryt::ABSTRACT_OBJECT_TYPET if(type.id()==ID_signedbv || type.id()==ID_unsignedbv || type.id()==ID_floatbv || type.id()==ID_fixedbv || - type.id()==ID_c_bool) + type.id()==ID_c_bool || type.id()==ID_bool) { abstract_object_type=CONSTANT; } From 0d147a356ab5a2a82834181e0fe3bc3e883efa72 Mon Sep 17 00:00:00 2001 From: Owen Jones Date: Wed, 8 Mar 2017 17:11:00 +0000 Subject: [PATCH 073/129] Fix overwrite for CLONE and MERGE MERGE is only ever used in derived classes, abstract_objectt has the base implementation (that's kind of the point) so the macro can simply include override. CLONE is only used in one place without override so I've added it to the macro and given an explicit basic implementation. Mark some functions const and/or override. This gets ride of warnings --- src/analyses/variable-sensitivity/abstract_object.h | 11 ++++++++--- .../variable-sensitivity/constant_abstract_value.h | 4 ++-- .../constant_pointer_abstract_object.h | 8 ++++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index dd58f110f1f..012948fd674 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -34,7 +34,7 @@ class namespacet; #define CLONE \ - virtual abstract_objectt* clone() const \ + virtual abstract_objectt* clone() const override \ { \ typedef std::remove_const::type \ >::type current_typet; \ @@ -44,7 +44,7 @@ class namespacet; #define MERGE(parent_typet) \ virtual abstract_object_pointert merge( \ const abstract_object_pointert op, \ - bool &out_any_modifications) \ + bool &out_any_modifications) override \ {\ assert(type()==op->type()); \ typedef std::remove_const::type \ @@ -125,7 +125,12 @@ class abstract_objectt virtual void output( std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; - CLONE + virtual abstract_objectt* clone() const // Macro is not used as this does not override + { + typedef std::remove_const::type + >::type current_typet; + return new current_typet(*this); + } private: // To enforce copy-on-write these are private and have read-only accessors typet t; diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 75123e01550..7a4f5bc4eda 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -26,12 +26,12 @@ class constant_abstract_valuet : public abstract_valuet CLONE MERGE(abstract_valuet) - virtual exprt to_constant (void) const; + virtual exprt to_constant (void) const override; virtual void output( std::ostream &out, const class ai_baset &ai, - const class namespacet &ns) const; + const class namespacet &ns) const override; protected : bool merge_state( diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 60f54f39389..6c6c41f1a28 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -35,19 +35,19 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt const constant_pointer_abstract_pointert op1, const constant_pointer_abstract_pointert op2); - exprt to_constant() const; + exprt to_constant() const override; void output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) const; + std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; abstract_object_pointert read_dereference( - const abstract_environmentt &env, const namespacet &ns) const; + const abstract_environmentt &env, const namespacet &ns) const override; sharing_ptrt write_dereference( abstract_environmentt &environment, const namespacet &ns, const std::stack stack, const abstract_object_pointert value, - bool merging_write); + bool merging_write) override; private: exprt value; From 20b2936bc2112c0b6bf97392755fb8daee3f0540 Mon Sep 17 00:00:00 2001 From: martin Date: Thu, 9 Mar 2017 20:26:27 +0000 Subject: [PATCH 074/129] In abstract objects the state should be private and merge_state protected. Again, this is to protected the copy-on-write nature of the objects against accidental wrong code. --- .../variable-sensitivity/abstract_object.h | 11 ++++++----- .../constant_abstract_value.h | 1 + .../constant_pointer_abstract_object.h | 9 +++++---- .../full_struct_abstract_object.h | 15 +++++++++------ 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 012948fd674..0dd4e0fe9ce 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -105,12 +105,9 @@ class abstract_objectt virtual bool is_top() const; virtual bool is_bottom() const; - // Sets the state of this object - bool merge_state( - const abstract_object_pointert op1, const abstract_object_pointert op2); - // This is both the interface and the base case of the recursion - // It uses merge state to + // It uses merge state to produce a new object of the most + // specific common parent type and is thus copy-on-write safe. virtual abstract_object_pointert merge( const abstract_object_pointert op, bool &out_any_modifications); @@ -140,6 +137,10 @@ class abstract_objectt protected: // The one exception is merge_state in descendent classes, which needs this void make_top() { top=true; } + + // Sets the state of this object + bool merge_state( + const abstract_object_pointert op1, const abstract_object_pointert op2); }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 7a4f5bc4eda..c3fe8d794d4 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -38,6 +38,7 @@ protected : constant_abstract_value_pointert op1, constant_abstract_value_pointert op2); +private : exprt value; }; diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 6c6c41f1a28..2f1458152e0 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -31,10 +31,6 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt CLONE MERGE(pointer_abstract_objectt) - bool merge_state( - const constant_pointer_abstract_pointert op1, - const constant_pointer_abstract_pointert op2); - exprt to_constant() const override; void output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; @@ -49,6 +45,11 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt const abstract_object_pointert value, bool merging_write) override; +protected: + bool merge_state( + const constant_pointer_abstract_pointert op1, + const constant_pointer_abstract_pointert op2); + private: exprt value; diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 00bfe843d7f..863a81372db 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -29,12 +29,6 @@ class full_struct_abstract_objectt:public struct_abstract_objectt CLONE MERGE(struct_abstract_objectt) - // Set the state of this to the merge result of op1 and op2 and - // return if the result is different from op1 - bool merge_state( - const sharing_ptrt op1, - const sharing_ptrt op2); - // struct interface virtual abstract_object_pointert read_component( const abstract_environmentt &environment, @@ -49,9 +43,18 @@ class full_struct_abstract_objectt:public struct_abstract_objectt const abstract_object_pointert value, bool merging_write) override; +private: // no entry means component is top typedef std::map struct_mapt; struct_mapt map; + +protected: + // Set the state of this to the merge result of op1 and op2 and + // return if the result is different from op1 + bool merge_state( + const sharing_ptrt op1, + const sharing_ptrt op2); + }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ONE_LEVEL_STRUCT_ABSTRACT_OBJECT_H From 6ff3ee79f917ecaf8d46dd06cb220218e0f58f69 Mon Sep 17 00:00:00 2001 From: martin Date: Thu, 9 Mar 2017 20:44:57 +0000 Subject: [PATCH 075/129] Enforced const interface for abstract objects The additional interfaces added by the direct children of abstract_objectt should be const. Made the abstract_object_pointert be const so only internal functions ever modify the abstract object. --- .../abstract_enviroment.cpp | 14 +++++------ .../variable-sensitivity/abstract_object.cpp | 5 ++-- .../variable-sensitivity/abstract_object.h | 24 ++++++++++++------- .../array_abstract_object.cpp | 2 +- .../array_abstract_object.h | 2 +- .../constant_pointer_abstract_object.cpp | 2 +- .../constant_pointer_abstract_object.h | 2 +- .../full_struct_abstract_object.cpp | 8 +++---- .../full_struct_abstract_object.h | 4 ++-- .../pointer_abstract_object.cpp | 2 +- .../pointer_abstract_object.h | 2 +- .../struct_abstract_object.cpp | 4 ++-- .../struct_abstract_object.h | 4 ++-- 13 files changed, 42 insertions(+), 33 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 6ff6dd446bb..78555b63c0b 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -76,7 +76,7 @@ abstract_object_pointert abstract_environmentt::eval( member_exprt member_expr(to_member_expr(expr)); sharing_ptrt struct_abstract_object= - std::dynamic_pointer_cast( + std::dynamic_pointer_cast( eval(member_expr.compound(), ns)); return struct_abstract_object->read_component(*this, member_expr, ns); @@ -86,7 +86,7 @@ abstract_object_pointert abstract_environmentt::eval( ID_address_of, [&](const exprt &expr) { sharing_ptrt pointer_object= - std::dynamic_pointer_cast( + std::dynamic_pointer_cast( abstract_object_factory(expr.type(), expr, ns)); // Store the abstract object in the pointer @@ -98,7 +98,7 @@ abstract_object_pointert abstract_environmentt::eval( { dereference_exprt dereference(to_dereference_expr(expr)); sharing_ptrt pointer_abstract_object= - std::dynamic_pointer_cast( + std::dynamic_pointer_cast( eval(dereference.pointer(), ns)); return pointer_abstract_object->read_dereference(*this, ns); @@ -109,7 +109,7 @@ abstract_object_pointert abstract_environmentt::eval( { index_exprt index_expr(to_index_expr(expr)); sharing_ptrt array_abstract_object= - std::dynamic_pointer_cast( + std::dynamic_pointer_cast( eval(index_expr.array(), ns)); return array_abstract_object->read_index(*this, index_expr, ns); @@ -309,7 +309,7 @@ abstract_object_pointert abstract_environmentt::write( abstract_object_pointert rhs_object) { sharing_ptrt array_abstract_object= - std::dynamic_pointer_cast(lhs_object); + std::dynamic_pointer_cast(lhs_object); sharing_ptrt modified_array= array_abstract_object->write_index( @@ -329,7 +329,7 @@ abstract_object_pointert abstract_environmentt::write( abstract_object_pointert rhs_object) { sharing_ptrt struct_abstract_object= - std::dynamic_pointer_cast(lhs_object); + std::dynamic_pointer_cast(lhs_object); sharing_ptrt modified_struct= struct_abstract_object->write_component( @@ -350,7 +350,7 @@ abstract_object_pointert abstract_environmentt::write( abstract_object_pointert rhs_object) { sharing_ptrt pointer_abstract_object= - std::dynamic_pointer_cast(lhs_object); + std::dynamic_pointer_cast(lhs_object); sharing_ptrt modified_pointer= pointer_abstract_object->write_dereference( diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index def354b411d..00b9d433beb 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -149,10 +149,11 @@ Function: abstract_objectt::merge \*******************************************************************/ abstract_object_pointert abstract_objectt::merge( - const abstract_object_pointert op, bool &out_any_modifications) + const abstract_object_pointert op, bool &out_any_modifications) const { assert(t==op->t); - abstract_object_pointert m=abstract_object_pointert(new abstract_objectt(*this)); + internal_abstract_object_pointert m= + internal_abstract_object_pointert(new abstract_objectt(*this)); out_any_modifications=m->merge_state(abstract_object_pointert(this), op); return m; } diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 0dd4e0fe9ce..0162a7791a9 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -44,7 +44,7 @@ class namespacet; #define MERGE(parent_typet) \ virtual abstract_object_pointert merge( \ const abstract_object_pointert op, \ - bool &out_any_modifications) override \ + bool &out_any_modifications) const override \ {\ assert(type()==op->type()); \ typedef std::remove_const::type \ @@ -55,9 +55,10 @@ class namespacet; "parent_typet in MERGE must be parent class of the current type"); \ \ typedef sharing_ptrt current_type_ptrt; \ + typedef internal_sharing_ptrt this_ptrt; \ /*Cast the supplied type to the current type to facilitate double dispatch*/ \ - current_type_ptrt n=std::dynamic_pointer_cast(op); \ - current_type_ptrt m=current_type_ptrt(new current_typet(*this)); \ + current_type_ptrt n=std::dynamic_pointer_cast(op); \ + this_ptrt m=this_ptrt(new current_typet(*this)); \ if (n!= NULL) \ { \ out_any_modifications=m->merge_state(current_type_ptrt(new current_typet(*this)), n); \ @@ -89,7 +90,7 @@ class namespacet; */ template -using sharing_ptrt=std::shared_ptr; +using sharing_ptrt=std::shared_ptr; typedef sharing_ptrt abstract_object_pointert; @@ -109,7 +110,7 @@ class abstract_objectt // It uses merge state to produce a new object of the most // specific common parent type and is thus copy-on-write safe. virtual abstract_object_pointert merge( - const abstract_object_pointert op, bool &out_any_modifications); + const abstract_object_pointert op, bool &out_any_modifications) const; // Interface for transforms abstract_object_pointert expression_transform( @@ -129,13 +130,20 @@ class abstract_objectt return new current_typet(*this); } -private: // To enforce copy-on-write these are private and have read-only accessors +private: + // To enforce copy-on-write these are private and have read-only accessors typet t; bool bottom; -protected: // TODO - remove +protected: + template + using internal_sharing_ptrt=std::shared_ptr; + + typedef internal_sharing_ptrt + internal_abstract_object_pointert; + bool top; -protected: // The one exception is merge_state in descendent classes, which needs this + // The one exception is merge_state in descendent classes, which needs this void make_top() { top=true; } // Sets the state of this object diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index e530bb6bfaf..017420ca702 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -145,7 +145,7 @@ sharing_ptrt array_abstract_objectt::write_index( const std::stack stack, const index_exprt &index_expr, const abstract_object_pointert value, - bool merging_write) + bool merging_write) const { // TODO(tkiley): Should this in fact havoc since we can't verify // that we are not writing past the end of the array - Martin said diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index f4f19903ccc..841c4e9e775 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -36,7 +36,7 @@ class array_abstract_objectt:public abstract_objectt abstract_environmentt &environment, const std::stack stack, const index_exprt &index_expr, const abstract_object_pointert value, - bool merging_write); + bool merging_write) const; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ARRAY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index e8b60f3551a..925507c4685 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -325,7 +325,7 @@ sharing_ptrt const namespacet &ns, const std::stack stack, const abstract_object_pointert new_value, - bool merging_write) + bool merging_write) const { if(is_top() || is_bottom()) { diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 2f1458152e0..ef113a5ded2 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -43,7 +43,7 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt const namespacet &ns, const std::stack stack, const abstract_object_pointert value, - bool merging_write) override; + bool merging_write) const override; protected: bool merge_state( diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 8fec8896a46..97d0b0f1992 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -121,7 +121,7 @@ Function: struct_abstract_objectt::read_component abstract_object_pointert full_struct_abstract_objectt::read_component( const abstract_environmentt &environment, const member_exprt &member_expr, - const namespacet& ns) + const namespacet& ns) const { #ifdef DEBUG std::cout << "Reading component " << member_expr.get_component_name() @@ -180,7 +180,7 @@ sharing_ptrt full_struct_abstract_objectt::write_compon const std::stack &stack, const member_exprt &member_expr, const abstract_object_pointert value, - bool merging_write) + bool merging_write) const { #ifdef DEBUG std::cout << "Writing component " << member_expr.get_component_name() @@ -197,7 +197,7 @@ sharing_ptrt full_struct_abstract_objectt::write_compon // we only handle one level currently if(!stack.empty()) { - sharing_ptrt copy( + internal_sharing_ptrt copy( new full_struct_abstract_objectt(*this)); irep_idt c=member_expr.get_component_name(); @@ -208,7 +208,7 @@ sharing_ptrt full_struct_abstract_objectt::write_compon } else { - sharing_ptrt copy( + internal_sharing_ptrt copy( new full_struct_abstract_objectt(*this)); #ifdef DEBUG diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 863a81372db..fadeae5dace 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -33,7 +33,7 @@ class full_struct_abstract_objectt:public struct_abstract_objectt virtual abstract_object_pointert read_component( const abstract_environmentt &environment, const member_exprt &member_expr, - const namespacet& ns) override; + const namespacet& ns) const override; virtual sharing_ptrt write_component( abstract_environmentt &environment, @@ -41,7 +41,7 @@ class full_struct_abstract_objectt:public struct_abstract_objectt const std::stack &stack, const member_exprt &member_expr, const abstract_object_pointert value, - bool merging_write) override; + bool merging_write) const override; private: // no entry means component is top diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index 3507e6e40bd..6b909a3f132 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -146,7 +146,7 @@ sharing_ptrt const namespacet &ns, const std::stack stack, const abstract_object_pointert value, - bool merging_write) + bool merging_write) const { if(is_top()) { diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index 1d54706c9bc..979f292b7c8 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -37,7 +37,7 @@ class pointer_abstract_objectt:public abstract_objectt const namespacet &ns, const std::stack stack, const abstract_object_pointert value, - bool merging_write); + bool merging_write) const; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_POINTER_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index 238fb88c531..fff7639fcc1 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -113,7 +113,7 @@ Function: struct_abstract_objectt::read_component abstract_object_pointert struct_abstract_objectt::read_component( const abstract_environmentt &environment, const member_exprt &member_expr, - const namespacet& ns) + const namespacet& ns) const { // If we are bottom then so are the components // otherwise the components could be anything @@ -147,7 +147,7 @@ sharing_ptrt struct_abstract_objectt::write_component( const std::stack &stack, const member_exprt &member_expr, const abstract_object_pointert value, - bool merging_write) + bool merging_write) const { if(is_top()) { diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index 44920e76cb6..e527e26af9a 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -30,7 +30,7 @@ class struct_abstract_objectt:public abstract_objectt virtual abstract_object_pointert read_component( const abstract_environmentt &environment, const member_exprt &member_expr, - const namespacet &ns); + const namespacet &ns) const; virtual sharing_ptrt write_component( abstract_environmentt &environment, @@ -38,7 +38,7 @@ class struct_abstract_objectt:public abstract_objectt const std::stack &stack, const member_exprt &member_expr, const abstract_object_pointert value, - bool merging_write); + bool merging_write) const; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H From e25d082a2c28375521c4ddf036db357700262abb Mon Sep 17 00:00:00 2001 From: Owen Jones Date: Thu, 9 Mar 2017 11:50:54 +0000 Subject: [PATCH 076/129] Fix crash The copy constructor for full_struct_abstract_objectt was failing to copy the map --- .../abstract_enviroment.cpp | 24 +++++++++++++++++++ .../abstract_enviroment.h | 2 ++ .../full_struct_abstract_object.cpp | 23 ++++++++++++++++-- .../full_struct_abstract_object.h | 1 + .../variable_sensitivity_domain.cpp | 4 ++++ 5 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 78555b63c0b..f16670c6658 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -700,6 +700,30 @@ void abstract_environmentt::output( out << "}\n"; } +/*******************************************************************\ + +Function: abstract_environmentt::verify + + Inputs: + + Outputs: + + Purpose: Check there aren't any null pointer mapped values + +\*******************************************************************/ + +bool abstract_environmentt::verify() const +{ + for(const auto &entry : map) + { + if(!entry.second) + { + return false; + } + } + return true; +} + abstract_object_pointert abstract_environmentt::eval_expression( const exprt &e, const namespacet &ns) const { diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 227a8455c87..7e447de17a1 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -62,6 +62,8 @@ class abstract_environmentt void output( std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; + bool verify() const; + protected: bool bottom; diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 97d0b0f1992..ca722b657f3 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -35,6 +35,7 @@ full_struct_abstract_objectt::full_struct_abstract_objectt(const typet &t): struct_abstract_objectt(t) { assert(t.id()==ID_struct); + assert(verify()); } /*******************************************************************\ @@ -58,6 +59,7 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( struct_abstract_objectt(t, top, bottom) { assert(t.id()==ID_struct); + assert(verify()); } /*******************************************************************\ @@ -77,7 +79,8 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( const full_struct_abstract_objectt &old): struct_abstract_objectt(old) { - + map=old.map; + assert(verify()); } /*******************************************************************\ @@ -98,6 +101,7 @@ full_struct_abstract_objectt::full_struct_abstract_objectt(const exprt &e): struct_abstract_objectt(e) { assert(e.type().id()==ID_struct); + assert(verify()); } /*******************************************************************\ @@ -203,7 +207,7 @@ sharing_ptrt full_struct_abstract_objectt::write_compon irep_idt c=member_expr.get_component_name(); copy->map[c]= environment.write(copy->map[c], value, stack, ns, merging_write); - + assert(copy->verify()); return copy; } else @@ -220,6 +224,7 @@ sharing_ptrt full_struct_abstract_objectt::write_compon if(merging_write) { if(is_top()) // struct is top + assert(copy->verify()); return copy; assert(!copy->map.empty()); @@ -229,6 +234,7 @@ sharing_ptrt full_struct_abstract_objectt::write_compon struct_mapt::iterator it=m.find(c); if(it==m.end()) // component is top + assert(copy->verify()); return copy; bool dummy; @@ -243,10 +249,16 @@ sharing_ptrt full_struct_abstract_objectt::write_compon assert(!copy->is_bottom()); } + assert(copy->verify()); return copy; } } +bool full_struct_abstract_objectt::verify() const +{ + return is_top() || is_bottom() || !map.empty(); +} + /*******************************************************************\ Function: full_struct_abstract_objectt::merge_state @@ -271,6 +283,7 @@ bool full_struct_abstract_objectt::merge_state( if(is_top() || is_bottom()) { map.clear(); + assert(verify()); return changed; } @@ -278,11 +291,15 @@ bool full_struct_abstract_objectt::merge_state( assert(!op1->is_bottom() && !op2->is_bottom()); if(op2->is_bottom()) + { + assert(verify()); return false; + } if(op1->is_bottom()) { map=op2->map; + assert(verify()); return true; } @@ -354,5 +371,7 @@ bool full_struct_abstract_objectt::merge_state( } } + assert(verify()); + return modified; } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index fadeae5dace..a4efdfa3599 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -49,6 +49,7 @@ class full_struct_abstract_objectt:public struct_abstract_objectt struct_mapt map; protected: + bool verify() const; // Set the state of this to the merge result of op1 and op2 and // return if the result is different from op1 bool merge_state( diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 692e3e06211..555955e2908 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -134,6 +134,8 @@ void variable_sensitivity_domaint::transform( default: throw "unrecognised instruction type"; } + + assert(abstract_state.verify()); } /*******************************************************************\ @@ -232,6 +234,8 @@ bool variable_sensitivity_domaint::merge( // Use the abstract_environment merge bool any_changes=abstract_state.merge(b.abstract_state); + + assert(abstract_state.verify()); return any_changes; } From 4a38df01b44d1ead284a1319c251d830948c9a31 Mon Sep 17 00:00:00 2001 From: Owen Jones Date: Thu, 9 Mar 2017 15:15:47 +0000 Subject: [PATCH 077/129] Minimal reproducer for struct problem --- .../minimal_reproducer_for_struct_problem.c | 28 +++++++++++++++++++ .../test.desc | 15 ++++++++++ 2 files changed, 43 insertions(+) create mode 100644 regression/goto-analyzer/minimal-reproducer-for-struct-problem/minimal_reproducer_for_struct_problem.c create mode 100644 regression/goto-analyzer/minimal-reproducer-for-struct-problem/test.desc diff --git a/regression/goto-analyzer/minimal-reproducer-for-struct-problem/minimal_reproducer_for_struct_problem.c b/regression/goto-analyzer/minimal-reproducer-for-struct-problem/minimal_reproducer_for_struct_problem.c new file mode 100644 index 00000000000..a484f619fe5 --- /dev/null +++ b/regression/goto-analyzer/minimal-reproducer-for-struct-problem/minimal_reproducer_for_struct_problem.c @@ -0,0 +1,28 @@ +#include + +int main(int argc, char *argv[]) +{ + // Test if we can represent constant structs + struct int_struct + { + int a; + }; + + struct int_struct x = {0}; + x.a = 0; + assert(x.a==0); + assert(x.a==1); + + if(argc>2) + { + assert(x.a==0); + assert(x.a==1); + x.a=1; + assert(x.a==0); + assert(x.a==1); + } + assert(x.a==0); + assert(x.a==1); + + return 0; +} diff --git a/regression/goto-analyzer/minimal-reproducer-for-struct-problem/test.desc b/regression/goto-analyzer/minimal-reproducer-for-struct-problem/test.desc new file mode 100644 index 00000000000..e68739d9b9b --- /dev/null +++ b/regression/goto-analyzer/minimal-reproducer-for-struct-problem/test.desc @@ -0,0 +1,15 @@ +CORE +minimal_reproducer_for_struct_problem.c +--variable --structs --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] .* assertion x.a==0: Success$ +^\[main.assertion.2\] .* assertion x.a==1: Failure \(if reachable\)$ +^\[main.assertion.3\] .* assertion x.a==0: Success$ +^\[main.assertion.4\] .* assertion x.a==1: Failure \(if reachable\)$ +^\[main.assertion.5\] .* assertion x.a==0: Failure \(if reachable\)$ +^\[main.assertion.6\] .* assertion x.a==1: Success$ +^\[main.assertion.7\] .* assertion x.a==0: Unknown$ +^\[main.assertion.8\] .* assertion x.a==1: Unknown$ +-- +^warning: ignoring From 7db370c8cc1f0a21acb7eb8fa29c641db236615d Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Mar 2017 17:18:57 +0000 Subject: [PATCH 078/129] Use the correct abstract object when performing a transform --- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index f16670c6658..b1ef325ed57 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -729,6 +729,6 @@ abstract_object_pointert abstract_environmentt::eval_expression( { // Delegate responsibility of resolving to a boolean abstract object // to the abstract object being compared against - abstract_object_pointert lhs=eval(e.op0(), ns); - return lhs->expression_transform(e, *this, ns); + abstract_object_pointert eval_obj=abstract_object_factory(e.type(), e, ns); + return eval_obj->expression_transform(e, *this, ns); } From 4e5a3adddab319ab209084e1aa1919a93069322d Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Mar 2017 17:18:37 +0000 Subject: [PATCH 079/129] Corrected merge action in the abstract enviroment --- .../variable-sensitivity/abstract_enviroment.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index b1ef325ed57..293b0cb9bb5 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -545,15 +545,14 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) modified|=object_modified; map[entry.first]=new_object; - } - - if(map[entry.first]->is_top()) - { - map.erase(entry.first); - modified=true; + if(map[entry.first]->is_top()) + { + map.erase(entry.first); + modified=true; #ifdef DEBUG - std::cout << "Removing " << entry.first.get_identifier() << std::endl; + std::cout << "Removing " << entry.first.get_identifier() << std::endl; #endif + } } } @@ -569,7 +568,7 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) { map.erase(key_to_remove); #ifdef DEBUG - std::cout << "Removing " << key_to_remove.get_identifier() << std::endl; + std::cout << "Removing " << key_to_remove.get_identifier() << std::endl; #endif modified=true; } From 01dbc417468d46960278fbfe875c5d0e711d8c5f Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Mar 2017 17:19:20 +0000 Subject: [PATCH 080/129] Correct struct write for unknown component --- .../full_struct_abstract_object.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index ca722b657f3..10abedf66d8 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -204,9 +204,21 @@ sharing_ptrt full_struct_abstract_objectt::write_compon internal_sharing_ptrt copy( new full_struct_abstract_objectt(*this)); + abstract_object_pointert starting_value; irep_idt c=member_expr.get_component_name(); + if(map.find(c)==map.cend()) + { + starting_value= + environment.abstract_object_factory( + member_expr.type(), ns, true, false); + } + else + { + starting_value=map.at(c); + } + copy->map[c]= - environment.write(copy->map[c], value, stack, ns, merging_write); + environment.write(starting_value, value, stack, ns, merging_write); assert(copy->verify()); return copy; } From b83a34b3b4658ad9a35789f07baccf391430c547 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Mar 2017 18:04:19 +0000 Subject: [PATCH 081/129] Correcting type check in struct abstract object Comment out wrong assert This needs to do an ns.follow to make this valid. --- src/analyses/variable-sensitivity/struct_abstract_object.cpp | 2 +- .../variable-sensitivity/variable_sensitivity_object_factory.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index fff7639fcc1..1f3f7a6a94b 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -89,7 +89,7 @@ Function: struct_abstract_objectt::struct_abstract_objectt struct_abstract_objectt::struct_abstract_objectt(const exprt &e): abstract_objectt(e) { - assert(e.type().id()==ID_struct); +// assert(e.type().id()==ID_struct); } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index 9eddb8e6b3b..3c9a0bc156d 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -15,6 +15,7 @@ #include #include #include +#include class variable_sensitivity_object_factoryt @@ -91,7 +92,7 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: } else { - assert(type==e.type()); + assert(type==ns.follow(e.type())); return abstract_object_pointert(new abstract_object_classt(e)); } } From 41cb817841b5948757618f1ac71c1ece339d9ecd Mon Sep 17 00:00:00 2001 From: Owen Jones Date: Tue, 7 Mar 2017 16:59:21 +0000 Subject: [PATCH 082/129] Fix for crash Found a place where we forgot to use the abstract object factory --- src/analyses/variable-sensitivity/abstract_object.cpp | 6 +++--- .../variable-sensitivity/full_struct_abstract_object.cpp | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 00b9d433beb..7b1ce203b97 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -188,10 +188,10 @@ abstract_object_pointert abstract_objectt::expression_transform( if(lhs_value.is_nil()) { - // One of the values is true so we can't really do anything more with + // One of the values is not resolvable to a constant + // so we can't really do anything more with // this expression and should just return top for the result - return abstract_object_pointert( - new abstract_objectt(expr.type(), true, false)); + return environment.abstract_object_factory(expr.type(), ns, true, false); } else { diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 10abedf66d8..66775efca8e 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -100,7 +100,7 @@ Function: full_struct_abstract_objectt::full_struct_abstract_objectt full_struct_abstract_objectt::full_struct_abstract_objectt(const exprt &e): struct_abstract_objectt(e) { - assert(e.type().id()==ID_struct); + //assert(e.type().id()==ID_struct); assert(verify()); } @@ -236,8 +236,10 @@ sharing_ptrt full_struct_abstract_objectt::write_compon if(merging_write) { if(is_top()) // struct is top + { assert(copy->verify()); return copy; + } assert(!copy->map.empty()); @@ -246,8 +248,10 @@ sharing_ptrt full_struct_abstract_objectt::write_compon struct_mapt::iterator it=m.find(c); if(it==m.end()) // component is top + { assert(copy->verify()); return copy; + } bool dummy; From ca9d7087bd4265da033cf188ec0c9fe304571d14 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 10 Mar 2017 17:33:34 +0000 Subject: [PATCH 083/129] Basic implementation of the constant_array_abstract_object Don't ignore all assigns just because the array is top as it starts as top but we allow writing to an index to stopping it becoming top. Ignore array size as not yet set to a sensible value. --- src/analyses/Makefile | 3 +- .../abstract_enviroment.cpp | 1 + .../array_abstract_object.cpp | 1 + .../array_abstract_object.h | 4 +- .../constant_array_abstract_object.cpp | 203 ++++++++++++++++++ .../constant_array_abstract_object.h | 67 ++++++ .../variable_sensitivity_object_factory.cpp | 2 +- .../variable_sensitivity_object_factory.h | 1 + 8 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 src/analyses/variable-sensitivity/constant_array_abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/constant_array_abstract_object.h diff --git a/src/analyses/Makefile b/src/analyses/Makefile index 520987b2d40..d2b31e8838a 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -34,7 +34,8 @@ SRC = ai.cpp \ variable-sensitivity/struct_abstract_object.cpp \ variable-sensitivity/variable_sensitivity_domain.cpp \ variable-sensitivity/variable_sensitivity_object_factory.cpp \ - variable-sensitivity/full_struct_abstract_object.cpp + variable-sensitivity/full_struct_abstract_object.cpp \ + variable-sensitivity/constant_array_abstract_object.cpp \ # Empty last line INCLUDES= -I .. diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 293b0cb9bb5..06c33a15f8b 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -314,6 +314,7 @@ abstract_object_pointert abstract_environmentt::write( sharing_ptrt modified_array= array_abstract_object->write_index( *this, + ns, stack, to_index_expr(next_expr), rhs_object, diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 017420ca702..2550d9b0e19 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -142,6 +142,7 @@ Function: abstract_object_pointert array_abstract_objectt sharing_ptrt array_abstract_objectt::write_index( abstract_environmentt &environment, + const namespacet &ns, const std::stack stack, const index_exprt &index_expr, const abstract_object_pointert value, diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index 841c4e9e775..9ad95465d82 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -34,7 +34,9 @@ class array_abstract_objectt:public abstract_objectt virtual sharing_ptrt write_index( abstract_environmentt &environment, - const std::stack stack, const index_exprt &index_expr, + const namespacet &ns, + const std::stack stack, + const index_exprt &index_expr, const abstract_object_pointert value, bool merging_write) const; }; diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp new file mode 100644 index 00000000000..3d99482962a --- /dev/null +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -0,0 +1,203 @@ +/*******************************************************************\ + + Module: Variable Sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#include +#include +#include + +#include "constant_array_abstract_object.h" + +constant_array_abstract_objectt::constant_array_abstract_objectt(typet type): +array_abstract_objectt(type) +{} + +constant_array_abstract_objectt::constant_array_abstract_objectt( + typet type, bool top, bool bottom): +array_abstract_objectt(type, top, bottom) +{} + +constant_array_abstract_objectt::constant_array_abstract_objectt( + const constant_array_abstract_objectt &old): + array_abstract_objectt(old) +{ + for(const auto &entry : old.map) + { + map[entry.first]=abstract_object_pointert(entry.second->clone()); + } +} + +constant_array_abstract_objectt::constant_array_abstract_objectt( + const exprt &expr): + array_abstract_objectt(expr) +{ + //const array_exprt &starting_expr=to_array_expr(expr); + +} + +void constant_array_abstract_objectt::output( + std::ostream &out, const ai_baset &ai, const namespacet &ns) const +{ + if(is_top() || is_bottom()) + { + array_abstract_objectt::output(out, ai, ns); + } + else + { + out << "{"; + for(const auto &entry : map) + { + out << "[" << entry.first << "] = "; + entry.second->output(out, ai, ns); + out << "\n"; + } + out << "}"; + } +} + +abstract_object_pointert constant_array_abstract_objectt::read_index( + const abstract_environmentt &env, + const index_exprt &index, + const namespacet &ns) const +{ + mp_integer index_value; + if(eval_index(index, env, ns, index_value)) + { + // Here we are assuming it is always in bounds + if(map.find(index_value)==map.cend()) + { + return env.abstract_object_factory(type().subtype(), ns, true, false); + } + else + { + return map.find(index_value)->second; + } + } + else + { + // Reading from somewhere in the array + // TODO(tkiley): merge all the values of the array, we may be able to + // do better than returning top + return env.abstract_object_factory(type().subtype(), ns, true, false); + } +} + +sharing_ptrt + constant_array_abstract_objectt::write_index( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const index_exprt &index_expr, + const abstract_object_pointert value, + bool merging_write) const +{ + if(is_bottom()) + { + return array_abstract_objectt::write_index( + environment, ns, stack, index_expr, value, merging_write); + } + else + { + if(stack.empty()) + { + auto copy= + internal_sharing_ptrt( + new constant_array_abstract_objectt(*this)); + + mp_integer index_value; + if(!merging_write && eval_index(index_expr, environment, ns, index_value)) + { + if(is_top()) + { + copy->top=false; + } + + copy->map[index_value]=value; + return copy; + } + else + { + // try to write to all + // TODO(tkiley): Merge with each entry + return array_abstract_objectt::write_index( + environment, ns, stack, index_expr, value, merging_write); + } + } + else + { + auto copy= + internal_sharing_ptrt( + new constant_array_abstract_objectt(*this)); + + mp_integer index_value; + if(eval_index(index_expr, environment, ns, index_value)) + { + // Here we assume the write is in bounds + abstract_object_pointert array_entry; + if(map.find(index_value)==map.cend()) + { + array_entry=map.at(index_value); + } + else + { + array_entry=get_top_entry(environment, ns); + } + + if(is_top()) + { + copy->top=false; + } + copy->map[index_value]=environment.write( + array_entry, value, stack, ns, merging_write); + + return copy; + } + else + { + for(const auto &array_entry : map) + { + // Merging write since we don't know which index we are writing to + copy->map[array_entry.first]= + environment.write( + array_entry.second, value, stack, ns, true); + if(is_top()) + { + copy->top=false; + } + } + + return copy; + } + } + } +} + +// Purpose: Short hand method for creating a top element of the array +abstract_object_pointert constant_array_abstract_objectt::get_top_entry( + const abstract_environmentt &env, const namespacet &ns) const +{ + return env.abstract_object_factory(type().subtype(), ns, true, false); +} + +bool constant_array_abstract_objectt::eval_index( + const index_exprt &index, + const abstract_environmentt &env, + const namespacet &ns, + mp_integer &out_index) const +{ + abstract_object_pointert index_abstract_object=env.eval(index.index(), ns); + exprt value=index_abstract_object->to_constant(); + if(value.is_constant()) + { + constant_exprt constant_index=to_constant_expr(value); + out_index=binary2integer(id2string(constant_index.get_value()), false); + return true; + } + else + { + return false; + } +} diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h new file mode 100644 index 00000000000..fcf9c7b0587 --- /dev/null +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -0,0 +1,67 @@ +/*******************************************************************\ + + Module: Variable Sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ARRAY_ABSTRACT_OBJECT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ARRAY_ABSTRACT_OBJECT_H + +#include +#include +#include + +class ai_baset; + +class constant_array_abstract_objectt:public array_abstract_objectt +{ +private: + typedef sharing_ptrt const + constant_array_abstract_object_pointert; + +public: + explicit constant_array_abstract_objectt(typet type); + constant_array_abstract_objectt(typet type, bool top, bool bottom); + constant_array_abstract_objectt(const constant_array_abstract_objectt &old); + constant_array_abstract_objectt(const exprt &expr); + + CLONE + MERGE(array_abstract_objectt) + + void output( + std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; + + virtual abstract_object_pointert read_index( + const abstract_environmentt &env, + const index_exprt &index, + const namespacet &ns) const override; + + virtual sharing_ptrt write_index( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const index_exprt &index_expr, + const abstract_object_pointert value, + bool merging_write) const override; + +protected: + +private: + // Since we don't store for any index where the value is top + // we don't use a regular array but instead a map of array indices + // to the value at that index + typedef std::map array_mapt; + array_mapt map; + + bool eval_index( + const index_exprt &index, + const abstract_environmentt &env, + const namespacet &ns, + mp_integer &out_index) const; + + abstract_object_pointert get_top_entry( + const abstract_environmentt &env, const namespacet &ns) const; +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ARRAY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 906de5958bf..98744c7c669 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -101,7 +101,7 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: return initialize_abstract_object( followed_type, top, bottom, e, ns); case ARRAY_SENSITIVE: - return initialize_abstract_object( + return initialize_abstract_object( followed_type, top, bottom, e, ns); case ARRAY_INSENSITIVE: return initialize_abstract_object( diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index 3c9a0bc156d..5905841fae6 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include From 9b4707232fa40d1ac08216233bbedf1ab85365bf Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 15 Mar 2017 11:44:13 +0000 Subject: [PATCH 084/129] Array initialization now works with the abstract object Made the constructor for making an abstract object from an expression also take an abstract_enviromentt and a namespacet so can call environment.eval on parts of the expression (e.g. to get an abstract object for each entry in the array). Use at rather than the operator[] since const correct. --- .../abstract_enviroment.cpp | 9 ++++---- .../abstract_enviroment.h | 6 ++++- .../variable-sensitivity/abstract_object.cpp | 15 ++++++++----- .../variable-sensitivity/abstract_object.h | 5 ++++- .../variable-sensitivity/abstract_value.cpp | 22 +++++++++++++++++-- .../variable-sensitivity/abstract_value.h | 17 ++++++++------ .../array_abstract_object.cpp | 7 ++++-- .../array_abstract_object.h | 5 ++++- .../constant_abstract_value.cpp | 7 ++++-- .../constant_abstract_value.h | 12 +++++----- .../constant_array_abstract_object.cpp | 18 +++++++++++---- .../constant_array_abstract_object.h | 6 ++++- .../constant_pointer_abstract_object.cpp | 6 +++-- .../constant_pointer_abstract_object.h | 5 ++++- .../full_struct_abstract_object.cpp | 8 ++++--- .../full_struct_abstract_object.h | 5 ++++- .../pointer_abstract_object.cpp | 7 ++++-- .../pointer_abstract_object.h | 5 ++++- .../struct_abstract_object.cpp | 10 ++++++--- .../struct_abstract_object.h | 5 ++++- .../variable_sensitivity_object_factory.cpp | 19 ++++++++-------- .../variable_sensitivity_object_factory.h | 16 +++++++++++--- 22 files changed, 154 insertions(+), 61 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 06c33a15f8b..9aa222ca2bc 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -450,7 +450,8 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( const typet &type, const namespacet &ns, bool top, bool bottom) const { exprt empty_constant_expr=exprt(); - return abstract_object_factory(type, top, bottom, empty_constant_expr, ns); + return abstract_object_factory( + type, top, bottom, empty_constant_expr, *this, ns); } /*******************************************************************\ @@ -471,7 +472,7 @@ Function: abstract_environmentt::abstract_object_factory abstract_object_pointert abstract_environmentt::abstract_object_factory( const typet &type, const exprt &e, const namespacet &ns) const { - return abstract_object_factory(type, false, false, e, ns); + return abstract_object_factory(type, false, false, e, *this, ns); } /*******************************************************************\ @@ -493,10 +494,10 @@ Function: abstract_environmentt::abstract_object_factory abstract_object_pointert abstract_environmentt::abstract_object_factory( const typet &type, bool top, bool bottom, const exprt &e, - const namespacet &ns) const + const abstract_environmentt &environment, const namespacet &ns) const { return variable_sensitivity_object_factoryt::instance().get_abstract_object( - type, top, bottom, e, ns); + type, top, bottom, e, environment, ns); } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 7e447de17a1..050aff3ba94 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -76,7 +76,11 @@ class abstract_environmentt private: abstract_object_pointert abstract_object_factory( - const typet &type, bool top, bool bottom, const exprt &e, + const typet &type, + bool top, + bool bottom, + const exprt &e, + const abstract_environmentt &eviroment, const namespacet &ns) const; }; diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 7b1ce203b97..dd97eccaf0b 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -80,15 +80,20 @@ Function: abstract_objectt::abstract_objectt Inputs: expr - the expression to use as the starting pointer for an abstract object + environment - The environment this abstract object is being created in + ns - the namespace Outputs: - Purpose: + Purpose: Construct an abstract object from the expression \*******************************************************************/ -abstract_objectt::abstract_objectt(const exprt &expr): -t(expr.type()), bottom(false), top(true) +abstract_objectt::abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns): + t(expr.type()), bottom(false), top(true) {} /*******************************************************************\ @@ -210,11 +215,11 @@ abstract_object_pointert abstract_objectt::expression_transform( // but at the moment this produces a two value abstraction for type bool // so for now we force it to be the constant abstraction return abstract_object_pointert( - new constant_abstract_valuet(constant_expr)); + new constant_abstract_valuet(constant_expr, environment, ns)); } else { - return environment.abstract_object_factory(expr.type(), ns, true, false); + return environment.abstract_object_factory(expr.type(), expr, ns); } } diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 0162a7791a9..1929e768fce 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -100,7 +100,10 @@ class abstract_objectt abstract_objectt(const typet &type); abstract_objectt(const typet &type, bool top, bool bottom); abstract_objectt(const abstract_objectt &old); - abstract_objectt(const exprt &expr); + abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); const typet &type() const; virtual bool is_top() const; diff --git a/src/analyses/variable-sensitivity/abstract_value.cpp b/src/analyses/variable-sensitivity/abstract_value.cpp index 3f188de0851..812c3ef3662 100644 --- a/src/analyses/variable-sensitivity/abstract_value.cpp +++ b/src/analyses/variable-sensitivity/abstract_value.cpp @@ -67,6 +67,24 @@ abstract_valuet::abstract_valuet(const abstract_valuet &old): abstract_objectt(old) {} -abstract_valuet::abstract_valuet(const exprt &expr): - abstract_objectt(expr) +/*******************************************************************\ + +Function: abstract_valuet::abstract_valuet + + Inputs: + expr - the expression to use as the starting pointer for an abstract object + environment - The environment this abstract object is being created in + ns - the namespace + + Outputs: + + Purpose: Construct an abstract value from the expression + +\*******************************************************************/ + +abstract_valuet::abstract_valuet( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns): + abstract_objectt(expr, environment, ns) {} diff --git a/src/analyses/variable-sensitivity/abstract_value.h b/src/analyses/variable-sensitivity/abstract_value.h index 0dda25f2b38..c86f336bfb4 100644 --- a/src/analyses/variable-sensitivity/abstract_value.h +++ b/src/analyses/variable-sensitivity/abstract_value.h @@ -14,13 +14,16 @@ class abstract_valuet:public abstract_objectt { public: - abstract_valuet(const typet &type); - abstract_valuet(const typet &type, bool top, bool bottom); - abstract_valuet(const abstract_valuet &old); - abstract_valuet(const exprt &expr); - - CLONE - MERGE(abstract_objectt) + explicit abstract_valuet(const typet &type); + abstract_valuet(const typet &type, bool top, bool bottom); + abstract_valuet(const abstract_valuet &old); + abstract_valuet( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); + + CLONE + MERGE(abstract_objectt) }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_VALUE_H diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 2550d9b0e19..1ad995cc7d7 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -85,8 +85,11 @@ Function: array_abstract_objectt::array_abstract_objectt \*******************************************************************/ -array_abstract_objectt::array_abstract_objectt(const exprt &e): - abstract_objectt(e) +array_abstract_objectt::array_abstract_objectt( + const exprt &e, + const abstract_environmentt &environment, + const namespacet &ns): + abstract_objectt(e, environment, ns) { assert(e.type().id()==ID_array); } diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index 9ad95465d82..50906a6f0fd 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -22,7 +22,10 @@ class array_abstract_objectt:public abstract_objectt explicit array_abstract_objectt(const typet &type); array_abstract_objectt(const typet &type, bool top, bool bottom); explicit array_abstract_objectt(const array_abstract_objectt &old); - explicit array_abstract_objectt(const exprt &expr); + explicit array_abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); CLONE MERGE(abstract_objectt) diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index a01124faa19..70ec0d2a4e6 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -22,8 +22,11 @@ constant_abstract_valuet::constant_abstract_valuet( abstract_valuet(old), value(old.value) {} -constant_abstract_valuet::constant_abstract_valuet(const exprt e): - abstract_valuet(e.type(), false, false), value(e) +constant_abstract_valuet::constant_abstract_valuet( + const exprt e, + const abstract_environmentt &environment, + const namespacet &ns): + abstract_valuet(e.type(), false, false), value(e) {} exprt constant_abstract_valuet::to_constant() const diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index c3fe8d794d4..baf8d0db4af 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -18,10 +18,13 @@ class constant_abstract_valuet : public abstract_valuet constant_abstract_value_pointert; public: - constant_abstract_valuet(typet t); - constant_abstract_valuet(typet t, bool tp, bool bttm); - constant_abstract_valuet(const constant_abstract_valuet &old); - constant_abstract_valuet(const exprt e); + explicit constant_abstract_valuet(typet t); + constant_abstract_valuet(typet t, bool tp, bool bttm); + constant_abstract_valuet(const constant_abstract_valuet &old); + constant_abstract_valuet( + const exprt e, + const abstract_environmentt &environment, + const namespacet &ns); CLONE MERGE(abstract_valuet) @@ -40,7 +43,6 @@ protected : private : exprt value; - }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ABSTRACT_VALUE_H diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 3d99482962a..0ca4b1b7c82 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -31,11 +31,21 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( } constant_array_abstract_objectt::constant_array_abstract_objectt( - const exprt &expr): - array_abstract_objectt(expr) + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns): + array_abstract_objectt(expr, environment, ns) { - //const array_exprt &starting_expr=to_array_expr(expr); - + if(expr.id()==ID_array) + { + int index=0; + for(const exprt &entry : expr.operands()) + { + map[mp_integer(index)]=environment.eval(entry, ns); + ++index; + } + top=false; + } } void constant_array_abstract_objectt::output( diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index fcf9c7b0587..47ef26e0978 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -13,6 +13,7 @@ #include class ai_baset; +class abstract_environmentt; class constant_array_abstract_objectt:public array_abstract_objectt { @@ -24,7 +25,10 @@ class constant_array_abstract_objectt:public array_abstract_objectt explicit constant_array_abstract_objectt(typet type); constant_array_abstract_objectt(typet type, bool top, bool bottom); constant_array_abstract_objectt(const constant_array_abstract_objectt &old); - constant_array_abstract_objectt(const exprt &expr); + constant_array_abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); CLONE MERGE(array_abstract_objectt) diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 925507c4685..10f6da8f388 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -90,8 +90,10 @@ Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt \*******************************************************************/ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( - const exprt &e): - pointer_abstract_objectt(e) + const exprt &e, + const abstract_environmentt &environment, + const namespacet &ns): + pointer_abstract_objectt(e, environment, ns) { assert(e.type().id()==ID_pointer); diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index ef113a5ded2..8ee50718361 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -26,7 +26,10 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt constant_pointer_abstract_objectt( const constant_pointer_abstract_objectt &old); - constant_pointer_abstract_objectt(const exprt &expr); + constant_pointer_abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); CLONE MERGE(pointer_abstract_objectt) diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 66775efca8e..b781b021e2c 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -97,10 +97,12 @@ Function: full_struct_abstract_objectt::full_struct_abstract_objectt \*******************************************************************/ -full_struct_abstract_objectt::full_struct_abstract_objectt(const exprt &e): - struct_abstract_objectt(e) +full_struct_abstract_objectt::full_struct_abstract_objectt( + const exprt &e, + const abstract_environmentt &environment, + const namespacet &ns): + struct_abstract_objectt(e, environment, ns) { - //assert(e.type().id()==ID_struct); assert(verify()); } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index a4efdfa3599..7a98ee28429 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -24,7 +24,10 @@ class full_struct_abstract_objectt:public struct_abstract_objectt full_struct_abstract_objectt(const typet &type, bool top, bool bottom); explicit full_struct_abstract_objectt(const full_struct_abstract_objectt &old); - explicit full_struct_abstract_objectt(const exprt &expr); + explicit full_struct_abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); CLONE MERGE(struct_abstract_objectt) diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index 6b909a3f132..81a56a8ddc8 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -86,8 +86,11 @@ Function: pointer_abstract_objectt::pointer_abstract_objectt \*******************************************************************/ -pointer_abstract_objectt::pointer_abstract_objectt(const exprt &e): - abstract_objectt(e) +pointer_abstract_objectt::pointer_abstract_objectt( + const exprt &e, + const abstract_environmentt &environment, + const namespacet &ns): + abstract_objectt(e, environment, ns) { assert(e.type().id()==ID_pointer); } diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index 979f292b7c8..fb19d314a93 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -23,7 +23,10 @@ class pointer_abstract_objectt:public abstract_objectt explicit pointer_abstract_objectt(const typet &type); pointer_abstract_objectt(const typet &type, bool top, bool bottom); explicit pointer_abstract_objectt(const pointer_abstract_objectt &old); - explicit pointer_abstract_objectt(const exprt &e); + explicit pointer_abstract_objectt( + const exprt &e, + const abstract_environmentt &environment, + const namespacet &ns); CLONE MERGE(abstract_objectt) diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index 1f3f7a6a94b..800076fb859 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include "struct_abstract_object.h" @@ -86,10 +87,13 @@ Function: struct_abstract_objectt::struct_abstract_objectt \*******************************************************************/ -struct_abstract_objectt::struct_abstract_objectt(const exprt &e): - abstract_objectt(e) +struct_abstract_objectt::struct_abstract_objectt( + const exprt &e, + const abstract_environmentt &environment, + const namespacet &ns): + abstract_objectt(e, environment, ns) { -// assert(e.type().id()==ID_struct); + assert(ns.follow(e.type()).id()==ID_struct); } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index e527e26af9a..37a0a2f3340 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -21,7 +21,10 @@ class struct_abstract_objectt:public abstract_objectt explicit struct_abstract_objectt(const typet &type); struct_abstract_objectt(const typet &type, bool top, bool bottom); explicit struct_abstract_objectt(const struct_abstract_objectt &old); - explicit struct_abstract_objectt(const exprt &expr); + explicit struct_abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); CLONE MERGE(abstract_objectt) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 98744c7c669..444a40d259f 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -82,6 +82,7 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: bool top, bool bottom, const exprt &e, + const abstract_environmentt &environment, const namespacet &ns) { if(!initialized) @@ -99,32 +100,32 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: { case CONSTANT: return initialize_abstract_object( - followed_type, top, bottom, e, ns); + followed_type, top, bottom, e, environment, ns); case ARRAY_SENSITIVE: return initialize_abstract_object( - followed_type, top, bottom, e, ns); + followed_type, top, bottom, e, environment, ns); case ARRAY_INSENSITIVE: return initialize_abstract_object( - followed_type, top, bottom, e, ns); + followed_type, top, bottom, e, environment, ns); case POINTER_SENSITIVE: return initialize_abstract_object( - followed_type, top, bottom, e, ns); + followed_type, top, bottom, e, environment, ns); case POINTER_INSENSITIVE: return initialize_abstract_object( - followed_type, top, bottom, e, ns); + followed_type, top, bottom, e, environment, ns); case STRUCT_SENSITIVE: return initialize_abstract_object( - followed_type, top, bottom, e, ns); + followed_type, top, bottom, e, environment, ns); case STRUCT_INSENSITIVE: return initialize_abstract_object( - followed_type, top, bottom, e, ns); + followed_type, top, bottom, e, environment, ns); case TWO_VALUE: return initialize_abstract_object( - followed_type, top, bottom, e, ns); + followed_type, top, bottom, e, environment, ns); default: assert(false); return initialize_abstract_object( - followed_type, top, bottom, e, ns); + followed_type, top, bottom, e, environment, ns); } } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index 5905841fae6..1d3eac20f9c 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -27,7 +27,11 @@ class variable_sensitivity_object_factoryt return s_instance; } abstract_object_pointert get_abstract_object( - const typet type, bool top, bool bottom, const exprt &e, + const typet type, + bool top, + bool bottom, + const exprt &e, + const abstract_environmentt &environment, const namespacet &ns); void set_options(optionst &options); @@ -49,7 +53,11 @@ class variable_sensitivity_object_factoryt ABSTRACT_OBJECT_TYPET get_abstract_object_type(const typet type); template abstract_object_pointert initialize_abstract_object( - const typet type, bool top, bool bottom, const exprt &e, + const typet type, + bool top, + bool bottom, + const exprt &e, + const abstract_environmentt &enviroment, const namespacet &ns); bool has_variables_flag; bool has_structs_flag; @@ -84,6 +92,7 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: bool top, bool bottom, const exprt &e, + const abstract_environmentt &enviroment, const namespacet &ns) { if(top || bottom) @@ -94,7 +103,8 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: else { assert(type==ns.follow(e.type())); - return abstract_object_pointert(new abstract_object_classt(e)); + return abstract_object_pointert( + new abstract_object_classt(e, enviroment, ns)); } } From b23b7de6222d3c078e26d79dd96afaa3c4e2aa9b Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 16 Mar 2017 10:48:02 +0000 Subject: [PATCH 085/129] Added merge_state to constant_array_abstract_object Moved Daniel P's merging of the map into a templated function in abstract object as need the same logic for the arary. Uses this logic to implement merge_state for an array --- .../variable-sensitivity/abstract_object.h | 79 +++++++++++++++++++ .../constant_array_abstract_object.cpp | 31 ++++++++ .../constant_array_abstract_object.h | 3 + .../full_struct_abstract_object.cpp | 70 +--------------- 4 files changed, 115 insertions(+), 68 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 1929e768fce..412a28aee88 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -31,6 +31,7 @@ class namespacet; #include #include +#include #define CLONE \ @@ -152,6 +153,84 @@ class abstract_objectt // Sets the state of this object bool merge_state( const abstract_object_pointert op1, const abstract_object_pointert op2); + + template + static bool merge_maps( + const std::map &map1, + const std::map &map2, + std::map &out_map); }; +template +bool abstract_objectt::merge_maps( + const std::map &m1, + const std::map &m2, + std::map &out_map) +{ + out_map.clear(); + + typedef std::map abstract_object_mapt; + + typename abstract_object_mapt::const_iterator it1=m1.begin(); + typename abstract_object_mapt::const_iterator it2=m2.begin(); + + bool modified=false; + + while(true) + { + if(it1->firstfirst) + { + // element of m1 is not in m2 + + it1++; + modified=true; + if(it1==m1.end()) + break; + } + else if(it2->firstfirst) + { + // element of m2 is not in m1 + + it2++; + if(it2==m2.end()) + { + modified=true; // as there is a remaining element in m1 + break; + } + } + else + { + // merge entries + + const abstract_object_pointert &v1=it1->second; + const abstract_object_pointert &v2=it2->second; + + bool changes=false; + abstract_object_pointert v_new; + + v_new=v1->merge(v2, changes); + + modified|=changes; + + out_map[it1->first]=v_new; + + it1++; + + if(it1==m1.end()) + break; + + it2++; + + if(it2==m2.end()) + { + modified=true; // as there is a remaining element in m1 + break; + } + } + } + + return modified; +} + + #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 0ca4b1b7c82..4736f4e75da 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -48,6 +48,37 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( } } +bool constant_array_abstract_objectt::merge_state( + const constant_array_abstract_object_pointert op1, + const constant_array_abstract_object_pointert op2) +{ + bool parent_merge_change=array_abstract_objectt::merge_state(op1, op2); + if(is_top() || is_bottom()) + { + map.clear(); + return parent_merge_change; + } + else + { + if(op1->is_bottom()) + { + *this=*dynamic_cast(op2->clone()); + return true; + } + if(op2->is_bottom()) + { + *this=*dynamic_cast(op1->clone()); + return false; + } + + // Both not top or bottom + assert(!op1->is_top() && !op2->is_top()); + assert(!op1->is_bottom() && !op2->is_bottom()); + + return abstract_objectt::merge_maps(op1->map, op2->map, map); + } +} + void constant_array_abstract_objectt::output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const { diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index 47ef26e0978..056481309fc 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -50,6 +50,9 @@ class constant_array_abstract_objectt:public array_abstract_objectt bool merging_write) const override; protected: + bool merge_state( + const constant_array_abstract_object_pointert op1, + const constant_array_abstract_object_pointert op2); private: // Since we don't store for any index where the value is top diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index b781b021e2c..b8741e23310 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -321,75 +321,9 @@ bool full_struct_abstract_objectt::merge_state( return true; } - // at this point both are different from top and bottom - - const struct_mapt &m1=op1->map; - const struct_mapt &m2=op2->map; - - assert(!m1.empty()); - assert(!m2.empty()); - - map.clear(); - - struct_mapt::const_iterator it1=m1.begin(); - struct_mapt::const_iterator it2=m2.begin(); - - bool modified=false; - - while(true) - { - if(it1->firstfirst) - { - // element of m1 is not in m2 - - it1++; - modified=true; - if(it1==m1.end()) - break; - } - else if(it2->firstfirst) - { - // element of m2 is not in m1 - - it2++; - if(it2==m2.end()) - { - modified=true; // as there is a remaining element in m1 - break; - } - } - else - { - // merge entries - - const abstract_object_pointert &v1=it1->second; - const abstract_object_pointert &v2=it2->second; - - bool changes=false; - abstract_object_pointert v_new; - - v_new=v1->merge(v2, changes); - - modified|=changes; - - map[it1->first]=v_new; - - it1++; - if(it1==m1.end()) - break; - - it2++; - - if(it2==m2.end()) - { - modified=true; // as there is a remaining element in m1 - break; - } - } - } + // at this point both are different from top and bottom + return abstract_objectt::merge_maps(op1->map, op2->map, map); assert(verify()); - - return modified; } From 006b8126c5b4158379390d0ed038dd3fb3628b0f Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 16 Mar 2017 16:29:29 +0000 Subject: [PATCH 086/129] Adding function header comments --- .../array_abstract_object.cpp | 5 +- .../constant_array_abstract_object.cpp | 158 +++++++++++++++++- 2 files changed, 161 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 1ad995cc7d7..c67b89d0b45 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -78,6 +78,8 @@ Function: array_abstract_objectt::array_abstract_objectt Inputs: expr - the expression to use as the starting pointer for an abstract object + environment - the environment the abstract object is being created in + ns - the namespace Outputs: @@ -124,10 +126,11 @@ abstract_object_pointert array_abstract_objectt::read_index( /*******************************************************************\ -Function: abstract_object_pointert array_abstract_objectt +Function: array_abstract_objectt::write_index Inputs: environment - the abstract environment + ns - the namespace stack - the remaining stack of expressions on the LHS to evaluate index_expr - the expression uses to access a specific index value - the value we are trying to assign to that value in the array diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 4736f4e75da..2e063068e66 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -11,15 +11,57 @@ #include "constant_array_abstract_object.h" +/*******************************************************************\ + +Function: constant_array_abstract_objectt::constant_array_abstract_objectt + + Inputs: + type - the type the abstract_object is representing + + Outputs: + + Purpose: + +\*******************************************************************/ + constant_array_abstract_objectt::constant_array_abstract_objectt(typet type): array_abstract_objectt(type) {} +/*******************************************************************\ + +Function: constant_array_abstract_objectt::constant_array_abstract_objectt + + Inputs: + type - the type the abstract_object is representing + top - is the abstract_object starting as top + bottom - is the abstract_object starting as bottom + + Outputs: + + Purpose: Start the abstract object at either top or bottom or neither + Asserts if both top and bottom are true + +\*******************************************************************/ + constant_array_abstract_objectt::constant_array_abstract_objectt( typet type, bool top, bool bottom): array_abstract_objectt(type, top, bottom) {} +/*******************************************************************\ + +Function: constant_array_abstract_objectt::constant_array_abstract_objectt + + Inputs: + old - the abstract object to copy from + + Outputs: + + Purpose: + +\*******************************************************************/ + constant_array_abstract_objectt::constant_array_abstract_objectt( const constant_array_abstract_objectt &old): array_abstract_objectt(old) @@ -30,6 +72,21 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( } } +/*******************************************************************\ + +Function: constant_array_abstract_objectt::constant_array_abstract_objectt + + Inputs: + expr - the expression to use as the starting pointer for an abstract object + environment - the environment the abstract object is being created in + ns - the namespace + + Outputs: + + Purpose: + +\*******************************************************************/ + constant_array_abstract_objectt::constant_array_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, @@ -48,6 +105,21 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( } } +/*******************************************************************\ + +Function: constant_array_abstract_objectt::merge_state + + Inputs: + op1 - The first array to merge + op2 - The second to merge + + Outputs: Returns true if the resulting abstract object is different to op1 + + Purpose: To modify this to be a merged version of op1 and op2, returning + true if the result is different to op1 + +\*******************************************************************/ + bool constant_array_abstract_objectt::merge_state( const constant_array_abstract_object_pointert op1, const constant_array_abstract_object_pointert op2) @@ -79,6 +151,24 @@ bool constant_array_abstract_objectt::merge_state( } } +/*******************************************************************\ + +Function: constant_array_abstract_objectt::output + + Inputs: + out - the stream to write to + ai - the abstract interpreter that contains the abstract domain + (that contains the object ... ) + ns - the current namespace + + Outputs: + + Purpose: To provide a human readable string to the out representing + the current known value about this object. For this array we + print: { [0] - constant_array_abstract_objectt::write_index( abstract_environmentt &environment, @@ -216,13 +343,42 @@ sharing_ptrt } } -// Purpose: Short hand method for creating a top element of the array +/*******************************************************************\ + +Function: constant_array_abstract_objectt::get_top_entry + + Inputs: + environment - the abstract environment + ns - the namespace + + Outputs: An abstract object pointer of type type().subtype() (i.e. the + type of the array's values). + + Purpose: Short hand method for creating a top element of the array + +\*******************************************************************/ + abstract_object_pointert constant_array_abstract_objectt::get_top_entry( const abstract_environmentt &env, const namespacet &ns) const { return env.abstract_object_factory(type().subtype(), ns, true, false); } +/*******************************************************************\ + +Function: constant_array_abstract_objectt::eval_index + + Inputs: + environment - the abstract environment + ns - the namespace + + Outputs: An abstract object pointer of type type().subtype() (i.e. the + type of the array's values). + + Purpose: Short hand method for creating a top element of the array + +\*******************************************************************/ + bool constant_array_abstract_objectt::eval_index( const index_exprt &index, const abstract_environmentt &env, From 1b5c81e2ffad982e72347cfed3b728c7f61f954d Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Mar 2017 11:26:34 +0000 Subject: [PATCH 087/129] Removed unnecessary copies --- .../constant_array_abstract_object.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 2e063068e66..d2beaef9ce2 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -66,10 +66,7 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( const constant_array_abstract_objectt &old): array_abstract_objectt(old) { - for(const auto &entry : old.map) - { - map[entry.first]=abstract_object_pointert(entry.second->clone()); - } + map=old.map; } /*******************************************************************\ @@ -134,12 +131,11 @@ bool constant_array_abstract_objectt::merge_state( { if(op1->is_bottom()) { - *this=*dynamic_cast(op2->clone()); + map=op2->map; return true; } if(op2->is_bottom()) { - *this=*dynamic_cast(op1->clone()); return false; } From af4a943ab764affe1c0bc6dafe55fbc2095e49df Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Mar 2017 11:26:24 +0000 Subject: [PATCH 088/129] Updating the demo script --- regression/goto-analyzer/demo/main.c | 33 ++++++++++++++++++---------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/regression/goto-analyzer/demo/main.c b/regression/goto-analyzer/demo/main.c index f9120ad7f96..d96e402fdf3 100644 --- a/regression/goto-analyzer/demo/main.c +++ b/regression/goto-analyzer/demo/main.c @@ -82,17 +82,28 @@ void func(int unknown) int ** ypp = &yp; **ypp = *yp; - int i; - int array[4]; - - i = 0; - array[i] = i; - i = i+1; - array[i] = i; - i = i+1; - array[i] = i; - i = i+1; - array[i] = i; + int array[4] = {0, 1 , 2, 3}; + + assert(array[0] == 0); // Success + assert(array[3] == 3); // Success + + if(unknown > 10) + { + array[0] = 4; + array[1] = 1; + array[2] = 5; + } + else + { + array[0] = 4; + array[2] = 10; + } + + assert(array[0] == 4); // Success + assert(array[1] == 1); // Success + assert(array[2] == 5); // Unknown + assert(array[3] == 3); // Success + typedef struct { From 3cbc98be024d98b44d7b2308f421d07a35ab6f24 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Mar 2017 09:42:20 +0000 Subject: [PATCH 089/129] Adding output function to struct Fixes #87 --- .../full_struct_abstract_object.cpp | 34 +++++++++++++++++++ .../full_struct_abstract_object.h | 5 +++ 2 files changed, 39 insertions(+) diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index b8741e23310..3bda9d7106d 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -272,6 +272,40 @@ sharing_ptrt full_struct_abstract_objectt::write_compon } } +/*******************************************************************\ + +Function: full_struct_abstract_objectt::output + + Inputs: + out - the stream to write to + ai - the abstract interpreter that contains the abstract domain + (that contains the object ... ) + ns - the current namespace + + Outputs: + + Purpose: To provide a human readable string to the out representing + the current known value about this object. For this array we + print: { .component_name=first) + { + out << ", "; + } + out << "." << entry.first << "="; + entry.second->output(out, ai, ns); + } + out << "}"; +} + bool full_struct_abstract_objectt::verify() const { return is_top() || is_bottom() || !map.empty(); diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 7a98ee28429..dab3f6741ba 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -46,6 +46,11 @@ class full_struct_abstract_objectt:public struct_abstract_objectt const abstract_object_pointert value, bool merging_write) const override; + virtual void output( + std::ostream &out, + const class ai_baset &ai, + const class namespacet &ns) const override; + private: // no entry means component is top typedef std::map struct_mapt; From e453bef336084a9767e8defb0701fd24274a0672 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Mar 2017 09:43:59 +0000 Subject: [PATCH 090/129] Made verify stricter Previously we just checked that we couldn't get into a state where it wasn't top or bottom, but the map was empty. Now we verify the relation as an if and only if, so if it is top or bottom, then the map is empty. --- .../full_struct_abstract_object.cpp | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 3bda9d7106d..3df3987e075 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -79,8 +79,8 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( const full_struct_abstract_objectt &old): struct_abstract_objectt(old) { - map=old.map; - assert(verify()); + map=old.map; + assert(verify()); } /*******************************************************************\ @@ -306,9 +306,26 @@ void full_struct_abstract_objectt::output( out << "}"; } +/*******************************************************************\ + +Function: full_struct_abstract_objectt::verify + + Inputs: + + Outputs: Returns true if the struct is valid + + Purpose: To validate that the struct object is in a valid state. + This means either it is top or bottom, or if neither of those + then there exists something in the map of components. + If there is something in the map, then it can't be top or bottom + +\*******************************************************************/ + bool full_struct_abstract_objectt::verify() const { - return is_top() || is_bottom() || !map.empty(); + // Either the object is top or bottom (=> map empty) + // or the map is not empty => neither top nor bottom + return (is_top() || is_bottom()) == map.empty(); } /*******************************************************************\ From 0187b77ceabbd3a8d09bf2ab6bd83d811dd022aa Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Mar 2017 09:47:11 +0000 Subject: [PATCH 091/129] Fixed bug where top wasn't being cleared When writing to a component with a stack, we weren't removing the top flag. Enabled the test that was failing due to this bug. --- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../goto-analyzer/sensitivity-test-constants-struct/test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../goto-analyzer/sensitivity-test-two-value-struct/test.desc | 2 +- .../variable-sensitivity/full_struct_abstract_object.cpp | 1 + 12 files changed, 12 insertions(+), 11 deletions(-) diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/test.desc index a214499b34b..908eee17958 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_pointer_to_two_value_struct.c --variable --pointers --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/test.desc index 7b6ae24bf61..1fd0ef53aec 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_struct_of_constants_array.c --variable --structs --arrays --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/test.desc index b278a7ed47c..81727577440 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_struct_of_constants_pointer.c --variable --structs --pointers --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/test.desc index 28f2e09614a..4420e433c06 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_struct_of_constants_struct.c --variable --structs --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/test.desc index 30edb4b598c..3dd5505c955 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_struct_of_two_value_array.c --variable --structs --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/test.desc index ea3a9cadb69..5249580ade1 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_struct_of_two_value_pointer.c --variable --structs --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc index 64a15fcae85..bdf9535e008 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_struct.c --variable --structs --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/test.desc index e8773cf68fc..2276f289deb 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_two_value_struct_of_two_value_array.c --variable --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/test.desc index 06ebb29d047..abb9d40d9ae 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_two_value_struct_of_two_value_pointer.c --variable --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/test.desc index 450055d2be6..b541110804e 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_two_value_struct_of_two_value_struct.c --variable --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-struct/test.desc index 157a3b25968..7835ecb2c41 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-struct/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_two_value_struct.c --variable --verify ^EXIT=0$ diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 3df3987e075..92a1a5a15af 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -221,6 +221,7 @@ sharing_ptrt full_struct_abstract_objectt::write_compon copy->map[c]= environment.write(starting_value, value, stack, ns, merging_write); + copy->top=false; assert(copy->verify()); return copy; } From d466c89cea9b7f4c9c25d1c57298c218008e1cf1 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Mar 2017 10:10:10 +0000 Subject: [PATCH 092/129] Bug fixes for the array abstract object Enabling array tests Handler in eval for array since we don't need to run any transforms on it, we can just create the object directly. Corrected base class constructor to not return bottom when an unknown write is performed. Fixed issue where if we didn't find an entry we tried to return it. --- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../sensitivity-test-constants-array/test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../sensitivity-test-two-value-array/test.desc | 2 +- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 7 +++++++ .../variable-sensitivity/array_abstract_object.cpp | 7 ++++--- .../constant_array_abstract_object.cpp | 2 +- 12 files changed, 21 insertions(+), 13 deletions(-) diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/test.desc index c8db44a2c09..d7d2cf6516e 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_array_of_constants_array.c --variable --arrays --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc index 9242552c707..a41d340d49d 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_array_of_constants_pointer.c --variable --arrays --pointers --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc index 74f5f128ed6..168bf25a428 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_array_of_two_value_pointer.c --variable --arrays --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array/test.desc index b48a2c823ca..624689e233f 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_array.c --variable --arrays --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc index 7ccb164ab0f..b1b2a1d23b4 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_pointer_to_constants_array.c --variable --pointers --arrays --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc index 7121e17040d..a1b051e1508 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_constants_pointer_to_two_value_array.c --variable --pointers --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/test.desc index 2c2c3ed15a8..953508ea2a3 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_two_value_array_of_two_value_array.c --variable --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc index f9de8e20a03..c4f68f9fd9a 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_two_value_array_of_two_value_pointer.c --variable --verify ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-array/test.desc index 23ee78bd74f..aed3958cf63 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-array/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE sensitivity_test_two_value_array.c --variable --verify ^EXIT=0$ diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 9aa222ca2bc..6a1d58f26c8 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -70,6 +70,13 @@ abstract_object_pointert abstract_environmentt::eval( expr.type(), to_constant_expr(expr), ns); } }, + { + ID_array, [&](const exprt &expr) + { + return abstract_object_factory( + expr.type(), expr, ns); + } + }, { ID_member, [&](const exprt &expr) { diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index c67b89d0b45..cc68cd9f79f 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -158,14 +158,15 @@ sharing_ptrt array_abstract_objectt::write_index( // that we are not writing past the end of the array - Martin said // default should be not to, but perhaps for soundness the base class should // havoc and the default should derive from this. - if(is_top()) + if(is_top() || is_bottom()) { return sharing_ptrt( - new array_abstract_objectt(*this)); + dynamic_cast(clone())); + } else { return sharing_ptrt( - new array_abstract_objectt(type(), false, true)); + new array_abstract_objectt(type(), true, false)); } } diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index d2beaef9ce2..bf5fb91a45d 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -301,7 +301,7 @@ sharing_ptrt { // Here we assume the write is in bounds abstract_object_pointert array_entry; - if(map.find(index_value)==map.cend()) + if(map.find(index_value)!=map.cend()) { array_entry=map.at(index_value); } From 987ec238d43fddde2ad893dff7e0b418b636eee5 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Mar 2017 10:18:07 +0000 Subject: [PATCH 093/129] Corrected and simplified constructor for the pointer abstract object Before there was a way the expression could end up unitialized though this constructor. This change simplifies the constructor by setting it to the "unset" value first and then modifying it if we are able to. --- .../constant_pointer_abstract_object.cpp | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 10f6da8f388..b3a4c1adc8f 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -96,37 +96,23 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( pointer_abstract_objectt(e, environment, ns) { assert(e.type().id()==ID_pointer); + value=nil_exprt(); - // TODO(tkiley): Should here really be handling the different ways we - // can create a pointer if(e.id()==ID_address_of) { - //address_of_exprt address_expr(to_address_of_expr(e)); value=e; top=false; } - else + else if(e.id()==ID_constant) { - if(e.id()==ID_constant) + constant_exprt constant_expr(to_constant_expr(e)); + if(constant_expr.get_value()==ID_NULL) { - constant_exprt constant_expr(to_constant_expr(e)); - if(constant_expr.get_value()==ID_NULL) - { - value=e; - top=false; - } - else - { - // TODO(tkiley): These should probably be logged. - // unknown type - value=nil_exprt(); - } - } - else - { - value=nil_exprt(); + value=e; + top=false; } } + // Else unknown expression type - possibly we should handle more } /*******************************************************************\ From f1436e537232cceb65550fc79846d622d59cc744 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 24 Mar 2017 10:06:14 +0000 Subject: [PATCH 094/129] Corrected implementation of flow sensitivity It used to assume(!guard) when next==to under the assumption that this means we are not taking the jump. This doesn't work if the GOTO is jumping to the next line. Instead we first check that the target of the goto statement is not the same as the next line. If it is, we don't assume anything since any condition could be both true or false on the next line. If this isn't the case, then we use the target of the jump and the to variable to determine whether the jump was taken or not. --- .../variable_sensitivity_domain.cpp | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 555955e2908..f0a9066e841 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -75,15 +75,27 @@ void variable_sensitivity_domaint::transform( case GOTO: { - // TODO(tkiley): add support for flow sensitivity if (1) // (flow_sensitivity == FLOW_SENSITIVE) { + // Get the next line locationt next=from; next++; - if(next==to) - abstract_state.assume(not_exprt(instruction.guard), ns); - else - abstract_state.assume(instruction.guard, ns); + // Is this a GOTO to the next line (i.e. pointless) + if(next!=from->get_target()) + { + if(to==from->get_target()) + { + // The AI is exploring the branch where the jump is taken + abstract_state.assume(instruction.guard, ns); + } + else + { + // Exploring the path where the jump is not taken - therefore assume + // the condition is false + abstract_state.assume(not_exprt(instruction.guard), ns); + } + } + // ignore jumps to the next line, we can assume nothing } } break; From edacc16d879906846235b98314addaf7dba283b5 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 27 Mar 2017 14:54:12 +0100 Subject: [PATCH 095/129] Tidy up includes Include iosfwd in the places that use std::ostream& Reordered the includes according to the coding standard rules. --- .../variable-sensitivity/abstract_enviroment.cpp | 6 +++--- .../variable-sensitivity/abstract_enviroment.h | 1 + .../variable-sensitivity/abstract_object.cpp | 6 +++--- src/analyses/variable-sensitivity/abstract_object.h | 12 ++++++++---- .../variable-sensitivity/constant_abstract_value.cpp | 5 ++++- .../variable-sensitivity/constant_abstract_value.h | 2 ++ .../constant_array_abstract_object.cpp | 2 ++ .../constant_array_abstract_object.h | 2 ++ .../constant_pointer_abstract_object.cpp | 1 + .../constant_pointer_abstract_object.h | 2 ++ .../full_struct_abstract_object.cpp | 2 ++ .../full_struct_abstract_object.h | 1 + .../variable_sensitivity_domain.cpp | 1 + .../variable_sensitivity_domain.h | 1 + 14 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 6a1d58f26c8..46b2dca555e 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -5,12 +5,11 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ -#include "abstract_enviroment.h" - #include #include #include #include + #include #include #include @@ -20,11 +19,12 @@ #include #include - +#include "abstract_enviroment.h" #ifdef DEBUG #include #endif + /*******************************************************************\ Function: abstract_environmentt::eval diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 050aff3ba94..375fddc9129 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index dd97eccaf0b..881e742c06b 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -8,13 +8,13 @@ #include -#include -#include #include #include -#include #include +#include +#include +#include #include "abstract_object.h" diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 412a28aee88..b87f7b83109 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -24,15 +24,19 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H + + +#include +#include +#include + +#include + class typet; class constant_exprt; class abstract_environmentt; class namespacet; -#include -#include -#include - #define CLONE \ virtual abstract_objectt* clone() const override \ diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index 70ec0d2a4e6..639f99c3fcb 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -5,10 +5,13 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ -#include "constant_abstract_value.h" + +#include #include +#include "constant_abstract_value.h" + constant_abstract_valuet::constant_abstract_valuet(typet t): abstract_valuet(t), value() {} diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index baf8d0db4af..64923002f72 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -8,6 +8,8 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ABSTRACT_VALUE_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ABSTRACT_VALUE_H +#include + #include #include diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index bf5fb91a45d..1fadcee09fc 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -5,6 +5,8 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ +#include + #include #include #include diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index 056481309fc..99a61015c88 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -9,6 +9,8 @@ #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ARRAY_ABSTRACT_OBJECT_H #include +#include + #include #include diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index b3a4c1adc8f..d45df364ab4 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -6,6 +6,7 @@ \*******************************************************************/ +#include #include #include diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 8ee50718361..2f427503d28 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -8,6 +8,8 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_POINTER_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_POINTER_ABSTRACT_OBJECT_H +#include + #include class constant_pointer_abstract_objectt:public pointer_abstract_objectt diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 92a1a5a15af..d8647481ed0 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -6,6 +6,8 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ +#include + #include #include #include diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index dab3f6741ba..938d967363d 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -10,6 +10,7 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ONE_LEVEL_STRUCT_ABSTRACT_OBJECT_H #include +#include #include #include diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index f0a9066e841..a80bb907b8e 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -8,6 +8,7 @@ Date: April 2016 \*******************************************************************/ +#include #include #include diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 89dbfe1ae5e..c45ee040a91 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -64,6 +64,7 @@ into calls to eval, assume, assign and merge. #include #include +#include #include #include From 06f5a5820d00faf6bfd1ab772d17453395086d88 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Mar 2017 13:27:06 +0100 Subject: [PATCH 096/129] Correcting implemenations of the write methods for pointer and struct When writing to a dereferenced pointer when we have the two value (top/bottom) domain, if the pointer is top, it stays as top and if it is bottom, it stays as bottom. However, in all other cases it becomes top. Similarly for structs, the struct should be top unless it is bottom. --- .../variable-sensitivity/pointer_abstract_object.cpp | 6 +++--- .../variable-sensitivity/struct_abstract_object.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index 81a56a8ddc8..6609031df7d 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -151,15 +151,15 @@ sharing_ptrt const abstract_object_pointert value, bool merging_write) const { - if(is_top()) + if(is_top() || is_bottom()) { environment.havoc("Writing to a 2value pointer"); return sharing_ptrt( - new pointer_abstract_objectt(*this)); + dynamic_cast(clone())); } else { return sharing_ptrt( - new pointer_abstract_objectt(type(), false, true)); + new pointer_abstract_objectt(type(), true, false)); } } diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index 800076fb859..db98edce9f7 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -153,14 +153,14 @@ sharing_ptrt struct_abstract_objectt::write_component( const abstract_object_pointert value, bool merging_write) const { - if(is_top()) + if(is_top() || is_bottom()) { return sharing_ptrt( - new struct_abstract_objectt(*this)); + dynamic_cast(clone())); } else { return sharing_ptrt( - new struct_abstract_objectt(type(), false, true)); + new struct_abstract_objectt(type(), true, false)); } } From 21cc2dc68dea789ce13cf2e49882647f006dec96 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Mar 2017 14:25:06 +0100 Subject: [PATCH 097/129] Refactor the ai_simplify into a lhs function --- .../variable_sensitivity_domain.cpp | 106 +++++++++++------- .../variable_sensitivity_domain.h | 4 + 2 files changed, 68 insertions(+), 42 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index a80bb907b8e..76a9ceeaaba 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -275,48 +275,7 @@ bool variable_sensitivity_domaint::ai_simplify( { if (lhs) { - // Care must be taken here to give something that is still writable - if (condition.id()==ID_index) - { - index_exprt ie = to_index_expr(condition); - exprt index = ie.index(); - bool changed = ai_simplify(index, ns, false); - if (changed) - { - ie.index() = index; - condition = simplify_expr(ie, ns); - } - - return changed; - } - else if (condition.id()==ID_dereference) - { - dereference_exprt de = to_dereference_expr(condition); - exprt pointer = de.pointer(); - bool changed = ai_simplify(pointer, ns, false); - if (changed) - { - de.pointer() = pointer; - condition = simplify_expr(de, ns); // So *(&x) -> x - } - - return changed; - } - else if (condition.id()==ID_member) - { - member_exprt me = to_member_expr(condition); - exprt compound = me.compound(); - bool changed = ai_simplify(compound, ns, true); // <-- true! - if (changed) - { - me.compound() = compound; - condition = simplify_expr(me, ns); - } - - return changed; - } - else - return false; + return ai_simplify_lhs(condition, ns); } else { @@ -368,4 +327,67 @@ bool variable_sensitivity_domaint::is_top() const return abstract_state.is_top(); } +/*******************************************************************\ + +Function: variable_sensitivity_domaint::ai_simplify_lhs + + Inputs: + condition - the expression to simplify + ns - the namespace + + Outputs: True if simplified the condition. False otherwise. condition + will be updated with the simplified condition if it has worked + + Purpose: Use the information in the domain to simplify the expression + on the LHS of an assignment. This for example won't simplify symbols + to their values, but does simplify indices in arrays, members of + structs and dereferencing of pointers + +\*******************************************************************/ + +bool variable_sensitivity_domaint::ai_simplify_lhs( + exprt &condition, const namespacet &ns) const +{ + // Care must be taken here to give something that is still writable + if (condition.id()==ID_index) + { + index_exprt ie = to_index_expr(condition); + exprt index = ie.index(); + bool changed = ai_simplify(index, ns, false); + if (changed) + { + ie.index() = index; + condition = simplify_expr(ie, ns); + } + + return changed; + } + else if (condition.id()==ID_dereference) + { + dereference_exprt de = to_dereference_expr(condition); + exprt pointer = de.pointer(); + bool changed = ai_simplify(pointer, ns, false); + if (changed) + { + de.pointer() = pointer; + condition = simplify_expr(de, ns); // So *(&x) -> x + } + + return changed; + } + else if (condition.id()==ID_member) + { + member_exprt me = to_member_expr(condition); + exprt compound = me.compound(); + bool changed = ai_simplify(compound, ns, true); // <-- true! + if (changed) + { + me.compound() = compound; + condition = simplify_expr(me, ns); + } + return changed; + } + else + return false; +} diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index c45ee040a91..069bae6b35d 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -106,6 +106,10 @@ class variable_sensitivity_domaint : public ai_domain_baset bool is_top() const override; private: + bool ai_simplify_lhs( + exprt &condition, + const namespacet &ns) const; + abstract_environmentt abstract_state; }; From b1e2cc6f0f0a787f6e3ed3392cf0437d306b481f Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Mar 2017 14:30:33 +0100 Subject: [PATCH 098/129] Corrected constructing object for failed evaluation When the expression_transform is unable to do anything, we fall back to using the abstract object factory using the passed expression. --- .../variable-sensitivity/abstract_object.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 881e742c06b..01d4ab9e9ff 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -207,20 +207,7 @@ abstract_object_pointert abstract_objectt::expression_transform( } exprt simplified=simplify_expr(constant_replaced_expr, ns); - if(simplified.is_constant()) - { - constant_exprt constant_expr=to_constant_expr(simplified); - - // TODO(tkiley): This should be going through the abstract_object_factory - // but at the moment this produces a two value abstraction for type bool - // so for now we force it to be the constant abstraction - return abstract_object_pointert( - new constant_abstract_valuet(constant_expr, environment, ns)); - } - else - { - return environment.abstract_object_factory(expr.type(), expr, ns); - } + return environment.abstract_object_factory(simplified.type(), simplified, ns); } /*******************************************************************\ From 6a305a5e9ba9c529f2d53fb21a7cd9d654c983ec Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Mar 2017 17:12:14 +0100 Subject: [PATCH 099/129] Fixing constant propogation test The variable_sensitivity_domaint::ai_simplify was retuning true if it simplied, but it should have been returning true if no simplification was performed (as specified in ai.h). The tests also had the wrong number of goto statements, there are two in the original program, both of which are removed Some of the tests had unescaped strings so I fixed them and made the more consistent with the other tests as enabling them. Some tests were disabled, they look like the should work but currently return the wrong number of simplified assignments. Created issue diffblue/cbmc-toyota#112 to look into this more detail. --- .../constant_propagation_01/main.c | 5 +++-- .../constant_propagation_01/test.desc | 4 ++-- .../constant_propagation_02/test.desc | 2 +- .../constant_propagation_03/test.desc | 4 ++-- .../constant_propagation_04/test.desc | 4 ++-- .../constant_propagation_05/test.desc | 4 ++-- .../constant_propagation_07/test.desc | 4 ++-- .../constant_propagation_08/test.desc | 4 ++-- .../constant_propagation_09/test.desc | 4 ++-- .../constant_propagation_10/test.desc | 6 +++--- .../constant_propagation_11/test.desc | 8 +++---- .../constant_propagation_12/test.desc | 2 +- .../constant_propagation_13/test.desc | 4 ++-- .../constant_propagation_14/test.desc | 8 +++---- .../constant_propagation_15/test.desc | 6 +++--- .../variable_sensitivity_domain.cpp | 21 +++++++++---------- 16 files changed, 45 insertions(+), 45 deletions(-) diff --git a/regression/goto-analyzer/constant_propagation_01/main.c b/regression/goto-analyzer/constant_propagation_01/main.c index 6689d8d4562..0185f49f3c1 100644 --- a/regression/goto-analyzer/constant_propagation_01/main.c +++ b/regression/goto-analyzer/constant_propagation_01/main.c @@ -1,13 +1,14 @@ +#include int main() { int i, j=20; - + if (j==20) { int x=1,y=2,z; z=x+y; assert(z==3); } - + } diff --git a/regression/goto-analyzer/constant_propagation_01/test.desc b/regression/goto-analyzer/constant_propagation_01/test.desc index 185a69aceee..e10d3883cc4 100644 --- a/regression/goto-analyzer/constant_propagation_01/test.desc +++ b/regression/goto-analyzer/constant_propagation_01/test.desc @@ -1,9 +1,9 @@ -FUTURE +CORE main.c --variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 1, assigns: 5, function calls: 0$ +^Simplified: assert: 1, assume: 0, goto: 2, assigns: 5, function calls: 0$ ^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 12, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_02/test.desc b/regression/goto-analyzer/constant_propagation_02/test.desc index 2bff9d991d7..49b87fa3483 100644 --- a/regression/goto-analyzer/constant_propagation_02/test.desc +++ b/regression/goto-analyzer/constant_propagation_02/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE main.c --variable --simplify out.gb ^EXIT=0$ diff --git a/regression/goto-analyzer/constant_propagation_03/test.desc b/regression/goto-analyzer/constant_propagation_03/test.desc index 04bd07d905b..49b87fa3483 100644 --- a/regression/goto-analyzer/constant_propagation_03/test.desc +++ b/regression/goto-analyzer/constant_propagation_03/test.desc @@ -1,9 +1,9 @@ -FUTURE +CORE main.c --variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 6, function calls: 0$ ^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_04/test.desc b/regression/goto-analyzer/constant_propagation_04/test.desc index 04bd07d905b..49b87fa3483 100644 --- a/regression/goto-analyzer/constant_propagation_04/test.desc +++ b/regression/goto-analyzer/constant_propagation_04/test.desc @@ -1,9 +1,9 @@ -FUTURE +CORE main.c --variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 6, function calls: 0$ ^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_05/test.desc b/regression/goto-analyzer/constant_propagation_05/test.desc index eb40f0011a4..7af5c6610d3 100644 --- a/regression/goto-analyzer/constant_propagation_05/test.desc +++ b/regression/goto-analyzer/constant_propagation_05/test.desc @@ -1,8 +1,8 @@ -FUTURE +CORE main.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line 12 function main, assertion j!=3: Failure (if reachable)$ +^\[main\.assertion\.1\] .* assertion j != 3: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_07/test.desc b/regression/goto-analyzer/constant_propagation_07/test.desc index b28b7dbf209..d3336fc21c0 100644 --- a/regression/goto-analyzer/constant_propagation_07/test.desc +++ b/regression/goto-analyzer/constant_propagation_07/test.desc @@ -1,9 +1,9 @@ -FUTURE +KNOWNBUG main.c --variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 4, assigns: 10, function calls: 0$ +^Simplified: assert: 1, assume: 0, goto: 3, assigns: 10, function calls: 0$ ^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 10, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_08/test.desc b/regression/goto-analyzer/constant_propagation_08/test.desc index 4fe007ee5ae..4b10f41e952 100644 --- a/regression/goto-analyzer/constant_propagation_08/test.desc +++ b/regression/goto-analyzer/constant_propagation_08/test.desc @@ -1,6 +1,6 @@ -FUTURE +KNOWNBUG main.c ---variable --simplify out.gb +--variable --arrays --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 2, assigns: 5, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_09/test.desc b/regression/goto-analyzer/constant_propagation_09/test.desc index db1411d762e..eb8dcca3246 100644 --- a/regression/goto-analyzer/constant_propagation_09/test.desc +++ b/regression/goto-analyzer/constant_propagation_09/test.desc @@ -1,6 +1,6 @@ -FUTURE +KNOWNBUG main.c ---variable --simplify out.gb +--variable --arrays --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 3, assigns: 4, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_10/test.desc b/regression/goto-analyzer/constant_propagation_10/test.desc index 2ef09bbe42d..37206fe4887 100644 --- a/regression/goto-analyzer/constant_propagation_10/test.desc +++ b/regression/goto-analyzer/constant_propagation_10/test.desc @@ -1,8 +1,8 @@ -FUTURE +CORE main.c ---variable --verify +--variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line 10 function main, assertion a\[0\]==2: Failure$ +^\[main\.assertion\.1\] .* assertion a\[\(signed long int\)0\] == 2: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_11/test.desc b/regression/goto-analyzer/constant_propagation_11/test.desc index 419af4adee4..327325637a5 100644 --- a/regression/goto-analyzer/constant_propagation_11/test.desc +++ b/regression/goto-analyzer/constant_propagation_11/test.desc @@ -1,9 +1,9 @@ -FUTURE +CORE main.c ---variable --simplify out.gb +--variable --arrays --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 0$ -^Unmodified: assert: 0, assume: 0, goto: 0$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 5, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 10, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_12/test.desc b/regression/goto-analyzer/constant_propagation_12/test.desc index ef80ec9efbe..2c983dd21fa 100644 --- a/regression/goto-analyzer/constant_propagation_12/test.desc +++ b/regression/goto-analyzer/constant_propagation_12/test.desc @@ -1,4 +1,4 @@ -FUTURE +KNOWNBUG main.c --variable --simplify out.gb ^EXIT=0$ diff --git a/regression/goto-analyzer/constant_propagation_13/test.desc b/regression/goto-analyzer/constant_propagation_13/test.desc index 66c40c2416f..0b7f0cbfb1c 100644 --- a/regression/goto-analyzer/constant_propagation_13/test.desc +++ b/regression/goto-analyzer/constant_propagation_13/test.desc @@ -1,8 +1,8 @@ -FUTURE +CORE main.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line 9 function main, assertion y==0: Failure (if reachable)$ +^\[main\.assertion\.1\] .* assertion y == 0: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_14/test.desc b/regression/goto-analyzer/constant_propagation_14/test.desc index c6af06456ba..f9e545bc125 100644 --- a/regression/goto-analyzer/constant_propagation_14/test.desc +++ b/regression/goto-analyzer/constant_propagation_14/test.desc @@ -1,9 +1,9 @@ -FUTURE +CORE main.c ---variable --verify +--variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line 11 function main, assertion a\[0\]==1 || a\[0\]==2: Success$ -^\[main.assertion.2\] file main.c line 12 function main, assertion a\[0\]==1 && a\[0\]==2: Failure$ +\[main\.assertion\.1\] .* assertion tmp_if_expr\$1: Success$ +\[main\.assertion\.2\] .* assertion tmp_if_expr\$2: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_15/test.desc b/regression/goto-analyzer/constant_propagation_15/test.desc index ac820dfeec6..37206fe4887 100644 --- a/regression/goto-analyzer/constant_propagation_15/test.desc +++ b/regression/goto-analyzer/constant_propagation_15/test.desc @@ -1,8 +1,8 @@ -FUTURE +CORE main.c ---variable --verify +--variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line 9 function main, assertion a\[0\]==2: Failure$ +^\[main\.assertion\.1\] .* assertion a\[\(signed long int\)0\] == 2: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 76a9ceeaaba..5f318507061 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -261,8 +261,7 @@ Function: variable_sensitivity_domaint::ai_simplify ns - the namespace lhs - is the expression on the left hand side - Outputs: True if simplified the condition. False otherwise. condition - will be updated with the simplified condition if it has worked + Outputs: True if no simplification was made Purpose: Use the information in the domain to simplify the expression with respect to the current location. This may be able to @@ -282,13 +281,13 @@ bool variable_sensitivity_domaint::ai_simplify( sharing_ptrt res = abstract_state.eval(condition, ns); exprt c = res->to_constant(); - if (c.id() == ID_nil) // TODO : simplification within an expression - return false; + if(c.id() == ID_nil) // TODO : simplification within an expression + return true; else { - bool b = (condition!=c); + bool condition_changed = (condition!=c); condition = c; - return b; + return !condition_changed; } } assert(0); // All conditions should be handled @@ -335,7 +334,7 @@ Function: variable_sensitivity_domaint::ai_simplify_lhs condition - the expression to simplify ns - the namespace - Outputs: True if simplified the condition. False otherwise. condition + Outputs: True if condition did not change. False otherwise. condition will be updated with the simplified condition if it has worked Purpose: Use the information in the domain to simplify the expression @@ -360,7 +359,7 @@ bool variable_sensitivity_domaint::ai_simplify_lhs( condition = simplify_expr(ie, ns); } - return changed; + return !changed; } else if (condition.id()==ID_dereference) { @@ -373,7 +372,7 @@ bool variable_sensitivity_domaint::ai_simplify_lhs( condition = simplify_expr(de, ns); // So *(&x) -> x } - return changed; + return !changed; } else if (condition.id()==ID_member) { @@ -386,8 +385,8 @@ bool variable_sensitivity_domaint::ai_simplify_lhs( condition = simplify_expr(me, ns); } - return changed; + return !changed; } else - return false; + return true; } From aafe2fa7c454366ad732d904af2e34a2dde94a73 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Mar 2017 18:12:57 +0100 Subject: [PATCH 100/129] Linting fixes --- .../abstract_enviroment.cpp | 17 ++++++------ .../abstract_enviroment.h | 4 +-- .../variable-sensitivity/abstract_object.cpp | 2 +- .../variable-sensitivity/abstract_object.h | 15 ++++++----- .../array_abstract_object.cpp | 1 - .../constant_abstract_value.cpp | 4 +-- .../constant_abstract_value.h | 4 +-- .../constant_pointer_abstract_object.h | 5 +--- .../full_struct_abstract_object.cpp | 15 ++++++----- .../full_struct_abstract_object.h | 10 +++---- .../variable_sensitivity_domain.cpp | 27 +++++++++---------- .../variable_sensitivity_domain.h | 9 +++---- 12 files changed, 56 insertions(+), 57 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 46b2dca555e..655f77710f0 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -42,7 +42,7 @@ Function: abstract_environmentt::eval abstract_object_pointert abstract_environmentt::eval( const exprt &expr, const namespacet &ns) const { - if (bottom) + if(bottom) return abstract_object_factory(expr.type(), ns, false, true); typedef std::function eval_handlert; @@ -197,9 +197,9 @@ bool abstract_environmentt::assign( // we will work through the relevant abstract objects exprt s = expr; std::stack stactions; // I'm not a continuation, honest guv' - while (s.id() != ID_symbol) + while(s.id() != ID_symbol) { - if (s.id() == ID_index || s.id() == ID_member || s.id() == ID_dereference) + if(s.id() == ID_index || s.id() == ID_member || s.id() == ID_dereference) { stactions.push(s); s = s.op0(); @@ -247,7 +247,7 @@ bool abstract_environmentt::assign( // Write the value for the root symbol back into the map assert(lhs_type==rhs_type); - if (final_value->is_top()) + if(final_value->is_top()) { map.erase(symbol_expr); } @@ -403,11 +403,12 @@ bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) exprt possibly_constant = res->to_constant(); - if (possibly_constant.id()!=ID_nil) // I.E. actually a value + if(possibly_constant.id()!=ID_nil) // I.E. actually a value { - assert(possibly_constant.type().id()==ID_bool); // Should be of the right type + // Should be of the right type + assert(possibly_constant.type().id()==ID_bool); - if (possibly_constant.is_false()) + if(possibly_constant.is_false()) { bool currently_bottom = is_bottom(); make_bottom(); @@ -543,7 +544,7 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) else { bool modified=false; - for(const auto &entry:env.map) + for(const auto &entry : env.map) { if(map.find(entry.first)!=map.end()) { diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 375fddc9129..bd6e9c0fdb0 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -68,8 +68,8 @@ class abstract_environmentt protected: bool bottom; - // We may need to break out more of these cases into these - virtual abstract_object_pointert eval_expression( + // We may need to break out more of these cases into these + virtual abstract_object_pointert eval_expression( const exprt &e, const namespacet &ns) const; typedef symbol_exprt map_keyt; diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 01d4ab9e9ff..1b87ea3087b 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -132,7 +132,7 @@ Function: abstract_objectt::merge_state bool abstract_objectt::merge_state( const abstract_object_pointert op1, const abstract_object_pointert op2) { - top=op1->top||op2->top; + top=op1->top || op2->top; bottom=op1->bottom && op2->bottom; assert(!(top && bottom)); diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index b87f7b83109..d59c1afc541 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -61,12 +61,14 @@ class namespacet; \ typedef sharing_ptrt current_type_ptrt; \ typedef internal_sharing_ptrt this_ptrt; \ - /*Cast the supplied type to the current type to facilitate double dispatch*/ \ + /* Cast the supplied type to the current type to */ \ + /* facilitate double dispatch*/ \ current_type_ptrt n=std::dynamic_pointer_cast(op); \ this_ptrt m=this_ptrt(new current_typet(*this)); \ - if (n!= NULL) \ + if(n!= NULL) \ { \ - out_any_modifications=m->merge_state(current_type_ptrt(new current_typet(*this)), n); \ + out_any_modifications= \ + m->merge_state(current_type_ptrt(new current_typet(*this)), n); \ return m; \ } \ else \ @@ -95,14 +97,14 @@ class namespacet; */ template -using sharing_ptrt=std::shared_ptr; +using sharing_ptrt=std::shared_ptr; // NOLINT(*) typedef sharing_ptrt abstract_object_pointert; class abstract_objectt { public: - abstract_objectt(const typet &type); + explicit abstract_objectt(const typet &type); abstract_objectt(const typet &type, bool top, bool bottom); abstract_objectt(const abstract_objectt &old); abstract_objectt( @@ -131,7 +133,8 @@ class abstract_objectt virtual void output( std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; - virtual abstract_objectt* clone() const // Macro is not used as this does not override + // Macro is not used as this does not override + virtual abstract_objectt* clone() const { typedef std::remove_const::type >::type current_typet; diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index cc68cd9f79f..5b22bbd918d 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -162,7 +162,6 @@ sharing_ptrt array_abstract_objectt::write_index( { return sharing_ptrt( dynamic_cast(clone())); - } else { diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index 639f99c3fcb..5e754549b1b 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -62,9 +62,9 @@ bool constant_abstract_valuet::merge_state( constant_abstract_value_pointert op2) { bool parent_merge_change=abstract_objectt::merge_state(op1, op2); - if (!is_top() && !is_bottom()) + if(!is_top() && !is_bottom()) { - if (op1->value==op2->value) + if(op1->value==op2->value) { value=op1->value; return false; diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 64923002f72..4902203a2b6 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -13,7 +13,7 @@ #include #include -class constant_abstract_valuet : public abstract_valuet +class constant_abstract_valuet:public abstract_valuet { private: typedef sharing_ptrt @@ -31,7 +31,7 @@ class constant_abstract_valuet : public abstract_valuet CLONE MERGE(abstract_valuet) - virtual exprt to_constant (void) const override; + virtual exprt to_constant() const override; virtual void output( std::ostream &out, diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 2f427503d28..55b80538438 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -18,7 +18,7 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt typedef sharing_ptrt constant_pointer_abstract_pointert; public: - constant_pointer_abstract_objectt(const typet &type); + explicit constant_pointer_abstract_objectt(const typet &type); constant_pointer_abstract_objectt( const typet &type, @@ -57,9 +57,6 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt private: exprt value; - - - }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_POINTER_ABSTRACT_OBJECT_H // NOLINT(*) diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index d8647481ed0..062c3ebb566 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -182,13 +182,14 @@ Function: struct_abstract_objectt::write_component \*******************************************************************/ -sharing_ptrt full_struct_abstract_objectt::write_component( - abstract_environmentt &environment, - const namespacet &ns, - const std::stack &stack, - const member_exprt &member_expr, - const abstract_object_pointert value, - bool merging_write) const +sharing_ptrt + full_struct_abstract_objectt::write_component( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack &stack, + const member_exprt &member_expr, + const abstract_object_pointert value, + bool merging_write) const { #ifdef DEBUG std::cout << "Writing component " << member_expr.get_component_name() diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 938d967363d..6caac30661a 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -6,8 +6,8 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ -#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ONE_LEVEL_STRUCT_ABSTRACT_OBJECT_H -#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ONE_LEVEL_STRUCT_ABSTRACT_OBJECT_H +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_FULL_STRUCT_ABSTRACT_OBJECT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_FULL_STRUCT_ABSTRACT_OBJECT_H #include #include @@ -24,8 +24,9 @@ class full_struct_abstract_objectt:public struct_abstract_objectt full_struct_abstract_objectt(const typet &type, bool top, bool bottom); - explicit full_struct_abstract_objectt(const full_struct_abstract_objectt &old); explicit full_struct_abstract_objectt( + const full_struct_abstract_objectt &old); + full_struct_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns); @@ -64,7 +65,6 @@ class full_struct_abstract_objectt:public struct_abstract_objectt bool merge_state( const sharing_ptrt op1, const sharing_ptrt op2); - }; -#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ONE_LEVEL_STRUCT_ABSTRACT_OBJECT_H +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_FULL_STRUCT_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 5f318507061..7b726e36492 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -76,7 +76,7 @@ void variable_sensitivity_domaint::transform( case GOTO: { - if (1) // (flow_sensitivity == FLOW_SENSITIVE) + if(1) // (flow_sensitivity == FLOW_SENSITIVE) { // Get the next line locationt next=from; @@ -272,25 +272,24 @@ Function: variable_sensitivity_domaint::ai_simplify bool variable_sensitivity_domaint::ai_simplify( exprt &condition, const namespacet &ns, const bool lhs) const { - if (lhs) + if(lhs) { return ai_simplify_lhs(condition, ns); } else { - sharing_ptrt res = abstract_state.eval(condition, ns); - exprt c = res->to_constant(); + sharing_ptrt res=abstract_state.eval(condition, ns); + exprt c=res->to_constant(); - if(c.id() == ID_nil) // TODO : simplification within an expression + if(c.id()==ID_nil) // TODO : simplification within an expression return true; else { - bool condition_changed = (condition!=c); - condition = c; + bool condition_changed=(condition!=c); + condition=c; return !condition_changed; } } - assert(0); // All conditions should be handled } /*******************************************************************\ @@ -348,12 +347,12 @@ bool variable_sensitivity_domaint::ai_simplify_lhs( exprt &condition, const namespacet &ns) const { // Care must be taken here to give something that is still writable - if (condition.id()==ID_index) + if(condition.id()==ID_index) { index_exprt ie = to_index_expr(condition); exprt index = ie.index(); bool changed = ai_simplify(index, ns, false); - if (changed) + if(changed) { ie.index() = index; condition = simplify_expr(ie, ns); @@ -361,12 +360,12 @@ bool variable_sensitivity_domaint::ai_simplify_lhs( return !changed; } - else if (condition.id()==ID_dereference) + else if(condition.id()==ID_dereference) { dereference_exprt de = to_dereference_expr(condition); exprt pointer = de.pointer(); bool changed = ai_simplify(pointer, ns, false); - if (changed) + if(changed) { de.pointer() = pointer; condition = simplify_expr(de, ns); // So *(&x) -> x @@ -374,12 +373,12 @@ bool variable_sensitivity_domaint::ai_simplify_lhs( return !changed; } - else if (condition.id()==ID_member) + else if(condition.id()==ID_member) { member_exprt me = to_member_expr(condition); exprt compound = me.compound(); bool changed = ai_simplify(compound, ns, true); // <-- true! - if (changed) + if(changed) { me.compound() = compound; condition = simplify_expr(me, ns); diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 069bae6b35d..de12a3f52bd 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -59,8 +59,8 @@ into calls to eval, assume, assign and merge. \*******************************************************************/ -#ifndef CPROVER_GOTO_ANALYZER_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H -#define CPROVER_GOTO_ANALYZER_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H #include #include @@ -69,7 +69,7 @@ into calls to eval, assume, assign and merge. #include #include -class variable_sensitivity_domaint : public ai_domain_baset +class variable_sensitivity_domaint:public ai_domain_baset { public: virtual void transform( @@ -111,7 +111,6 @@ class variable_sensitivity_domaint : public ai_domain_baset const namespacet &ns) const; abstract_environmentt abstract_state; - }; -#endif // CPROVER_GOTO_ANALYZER_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H // NOLINT(*) +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H From a8f1ae71563ec1180996d59dea07868fcc053223 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 29 Mar 2017 17:25:38 +0100 Subject: [PATCH 101/129] Modified lambda to compile under Windows compiler. --- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 655f77710f0..5460bbec235 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -59,7 +59,8 @@ abstract_object_pointert abstract_environmentt::eval( } else { - return symbol_entry->second; + abstract_object_pointert found_symbol_value=symbol_entry->second; + return found_symbol_value; } } }, From c49b533af342f6592772a39ba4ff61166ddd7ad0 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 19 Apr 2017 17:01:45 +0100 Subject: [PATCH 102/129] Improved the removing top elements in map merge As opposed to iterating over the map twice, we remove as we move through the map --- .../int_sensitivity_tests.c | 22 +++++++++++ .../sensitivity-test-constants-int/test.desc | 5 +++ .../abstract_enviroment.cpp | 37 ++++++++++++------- 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/regression/goto-analyzer/sensitivity-test-common-files/int_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/int_sensitivity_tests.c index ab4265a051f..fab9e36038a 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/int_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/int_sensitivity_tests.c @@ -51,5 +51,27 @@ int main(int argc, char *argv[]) assert(y==0); } + // Try merging two states with multiple variables + + int a1 = 0; + int a2 = 0; + int a3 = 0; + int a4 = 0; + int a5 = 0; + if(argc > 2) + { + a1 = argc; + a2 = argc; + a3 = argc; + // all three variables are now top in this branch + } + + // all three asserts are unverifiable + assert(a1==0); + assert(a2==0); + assert(a3==0); + assert(a4==0); + assert(a5==0); + return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-constants-int/test.desc b/regression/goto-analyzer/sensitivity-test-constants-int/test.desc index 20156736ef1..994707c59db 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-int/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-int/test.desc @@ -26,5 +26,10 @@ sensitivity_test_constants_int.c ^\[main.assertion.21\] .* assertion x==0: Success \(unreachable\)$ ^\[main.assertion.22\] .* assertion x==1: Success \(unreachable\)$ ^\[main.assertion.23\] .* assertion y==0: Success \(unreachable\)$ +^\[main.assertion.24\] .* assertion a1==0: Unknown$ +^\[main.assertion.25\] .* assertion a2==0: Unknown$ +^\[main.assertion.26\] .* assertion a3==0: Unknown$ +^\[main.assertion.27\] .* assertion a4==0: Success$ +^\[main.assertion.28\] .* assertion a5==0: Success$ -- ^warning: ignoring diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 5460bbec235..f2df43615ba 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -531,8 +531,6 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) // for each entry in the incoming environment we need to either add it // if it is new, or merge with the existing key if it is not present - - if(bottom) { *this=env; @@ -544,6 +542,8 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) } else { + // For each element in the intersection of map and env.map merge + // If the result of the merge is top, remove from the map bool modified=false; for(const auto &entry : env.map) { @@ -553,7 +553,7 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) abstract_object_pointert new_object=map[entry.first]->merge( entry.second, object_modified); - modified|=object_modified; + modified|=object_modified; map[entry.first]=new_object; if(map[entry.first]->is_top()) @@ -565,23 +565,32 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) #endif } } - } - - std::vector to_remove; - for(const auto &entry : map) - { - if(env.map.find(entry.first)==env.map.end()) + else { - to_remove.push_back(entry.first); + // Map doesn't contain key so the resulting map shouldn't either } } - for(const map_keyt &key_to_remove : to_remove) + + // Remove all elements from the map that are not present in the map we are + // merging in since they must be top + const auto &end_iter=map.end(); + for(auto iter=map.begin(); iter!=end_iter;) { - map.erase(key_to_remove); + if(env.map.find(iter->first)==env.map.cend()) + { + // After calling erase, the iterator is no longer valid, so we increment + // the iterator first and return a copy of the original iterator + map.erase(iter++); + modified=true; + #ifdef DEBUG - std::cout << "Removing " << key_to_remove.get_identifier() << std::endl; + std::cout << "Removing " << iter->first.get_identifier() << std::endl; #endif - modified=true; + } + else + { + ++iter; + } } return modified; From 6297a052a6708e62a7ed95bf051a9e1e9fabeeb8 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 5 Apr 2017 11:14:09 +0100 Subject: [PATCH 103/129] Modified code to not crash when writing to an pointer arithmetic on lhs When the lhs is unusual, we don't crash and instead create an abstract object based off its evaluation. --- .../pointer_to_array_sensitivity_tests.c | 4 ++ .../test.desc | 17 ++--- .../test.desc | 17 ++--- .../test.desc | 17 ++--- .../abstract_enviroment.cpp | 64 +++++++++++-------- 5 files changed, 70 insertions(+), 49 deletions(-) diff --git a/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c index db9fe720e15..b821af7a1f5 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c @@ -21,6 +21,10 @@ int main(int argc, char *argv[]) // Test writing into an array using a pointer *q=4; assert(a[1]==4); + + q[1]=5; + assert(a[1]==5); + a[1]=2; // We now explore pointers and indexes each with more than one possible value diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc index b1b2a1d23b4..ac4e32cfc0f 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc @@ -9,13 +9,14 @@ sensitivity_test_constants_pointer_to_constants_array.c ^\[main.assertion.4\] .* assertion \*q==2: Unknown$ ^\[main.assertion.5\] .* assertion q-p==x: Unknown$ ^\[main.assertion.6\] .* assertion a\[1\]==4: Unknown$ -^\[main.assertion.7\] .* assertion \*r==2: Unknown$ -^\[main.assertion.8\] .* assertion \*r==1: Unknown$ -^\[main.assertion.9\] .* assertion \*s==0: Unknown$ -^\[main.assertion.10\] .* assertion \*s==1: Unknown$ -^\[main.assertion.11\] .* assertion t==p\+i: Unknown$ -^\[main.assertion.12\] .* assertion t-p==y: Unknown$ -^\[main.assertion.13\] .* assertion a\[i\]==5: Unknown$ -^\[main.assertion.14\] .* assertion a\[1\]==5: Unknown$ +^\[main.assertion.7\] .* assertion a\[1\]==5: Unknown$ +^\[main.assertion.8\] .* assertion \*r==2: Unknown$ +^\[main.assertion.9\] .* assertion \*r==1: Unknown$ +^\[main.assertion.10\] .* assertion \*s==0: Unknown$ +^\[main.assertion.11\] .* assertion \*s==1: Unknown$ +^\[main.assertion.12\] .* assertion t==p\+i: Unknown$ +^\[main.assertion.13\] .* assertion t-p==y: Unknown$ +^\[main.assertion.14\] .* assertion a\[i\]==5: Unknown$ +^\[main.assertion.15\] .* assertion a\[1\]==5: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc index a1b051e1508..77e34834024 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc @@ -9,13 +9,14 @@ sensitivity_test_constants_pointer_to_two_value_array.c ^\[main.assertion.4\] .* assertion \*q==2: Unknown$ ^\[main.assertion.5\] .* assertion q-p==x: Unknown$ ^\[main.assertion.6\] .* assertion a\[1\]==4: Unknown$ -^\[main.assertion.7\] .* assertion \*r==2: Unknown$ -^\[main.assertion.8\] .* assertion \*r==1: Unknown$ -^\[main.assertion.9\] .* assertion \*s==0: Unknown$ -^\[main.assertion.10\] .* assertion \*s==1: Unknown$ -^\[main.assertion.11\] .* assertion t==p\+i: Unknown$ -^\[main.assertion.12\] .* assertion t-p==y: Unknown$ -^\[main.assertion.13\] .* assertion a\[i\]==5: Unknown$ -^\[main.assertion.14\] .* assertion a\[1\]==5: Unknown$ +^\[main.assertion.7\] .* assertion a\[1\]==5: Unknown$ +^\[main.assertion.8\] .* assertion \*r==2: Unknown$ +^\[main.assertion.9\] .* assertion \*r==1: Unknown$ +^\[main.assertion.10\] .* assertion \*s==0: Unknown$ +^\[main.assertion.11\] .* assertion \*s==1: Unknown$ +^\[main.assertion.12\] .* assertion t==p\+i: Unknown$ +^\[main.assertion.13\] .* assertion t-p==y: Unknown$ +^\[main.assertion.14\] .* assertion a\[i\]==5: Unknown$ +^\[main.assertion.15\] .* assertion a\[1\]==5: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc index 58bedcf1cc1..c4d829b7eea 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc @@ -9,13 +9,14 @@ sensitivity_test_two_value_pointer_to_two_value_array.c ^\[main.assertion.4\] .* assertion \*q==2: Unknown$ ^\[main.assertion.5\] .* assertion q-p==x: Unknown$ ^\[main.assertion.6\] .* assertion a\[1\]==4: Unknown$ -^\[main.assertion.7\] .* assertion \*r==2: Unknown$ -^\[main.assertion.8\] .* assertion \*r==1: Unknown$ -^\[main.assertion.9\] .* assertion \*s==0: Unknown$ -^\[main.assertion.10\] .* assertion \*s==1: Unknown$ -^\[main.assertion.11\] .* assertion t==p\+i: Unknown$ -^\[main.assertion.12\] .* assertion t-p==y: Unknown$ -^\[main.assertion.13\] .* assertion a\[i\]==5: Unknown$ -^\[main.assertion.14\] .* assertion a\[1\]==5: Unknown$ +^\[main.assertion.7\] .* assertion a\[1\]==5: Unknown$ +^\[main.assertion.8\] .* assertion \*r==2: Unknown$ +^\[main.assertion.9\] .* assertion \*r==1: Unknown$ +^\[main.assertion.10\] .* assertion \*s==0: Unknown$ +^\[main.assertion.11\] .* assertion \*s==1: Unknown$ +^\[main.assertion.12\] .* assertion t==p\+i: Unknown$ +^\[main.assertion.13\] .* assertion t-p==y: Unknown$ +^\[main.assertion.14\] .* assertion a\[i\]==5: Unknown$ +^\[main.assertion.15\] .* assertion a\[1\]==5: Unknown$ -- ^warning: ignoring diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index f2df43615ba..b28f4993c66 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -194,6 +194,7 @@ bool abstract_environmentt::assign( return !bottom_at_start; } + abstract_object_pointert lhs_value=nullptr; // Build a stack of index, member and dereference accesses which // we will work through the relevant abstract objects exprt s = expr; @@ -207,54 +208,67 @@ bool abstract_environmentt::assign( } else { - // Attempting to assign to something unreasonable - // Your goto-program is broken - std::ostringstream error_builder; - error_builder << "unsupported assign "; - error_builder << s.id(); - throw error_builder.str(); + lhs_value=eval(s, ns); + break; } } - const symbol_exprt &symbol_expr(to_symbol_expr(s)); - - // This is the root abstract object that is in the map of abstract objects - // It might not have the same type as value if the above stack isn't empty - abstract_object_pointert final_value; - - if(!stactions.empty()) + if(!lhs_value) { - // The symbol is not in the map - it is therefore top - abstract_object_pointert symbol_object; + assert(s.id()==ID_symbol); + const symbol_exprt &symbol_expr(to_symbol_expr(s)); if(map.find(symbol_expr)==map.end()) { - symbol_object=abstract_object_factory( + lhs_value=abstract_object_factory( symbol_expr.type(), ns, true, false); } else { - symbol_object=map[symbol_expr]; + lhs_value=map[symbol_expr]; } - final_value=write(symbol_object, value, stactions, ns, false); + } + + abstract_object_pointert final_value; + + // This is the root abstract object that is in the map of abstract objects + // It might not have the same type as value if the above stack isn't empty + + + if(!stactions.empty()) + { + // The symbol is not in the map - it is therefore top + final_value=write(lhs_value, value, stactions, ns, false); } else { + // If we don't have a symbol on the LHS, then we must have some expression + // that we can write to (i.e. a pointer, an array, a struct) This appears + // to be none of that. + if(s.id()!=ID_symbol) + { + throw "invalid l-value"; + } // We can assign the AO directly to the symbol final_value=value; } - const typet &lhs_type=ns.follow(symbol_expr.type()); + const typet &lhs_type=ns.follow(lhs_value->type()); const typet &rhs_type=ns.follow(final_value->type()); // Write the value for the root symbol back into the map assert(lhs_type==rhs_type); - if(final_value->is_top()) - { - map.erase(symbol_expr); - } - else + // If LHS was directly the symbol + if(s.id()==ID_symbol) { - map[symbol_expr]=final_value; + symbol_exprt symbol_expr=to_symbol_expr(s); + if(final_value->is_top()) + { + map.erase(symbol_expr); + } + else + { + map[symbol_expr]=final_value; + } } return true; } From 12f78b4676dcad084718dc3dfa097a9f6695f777 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 7 Apr 2017 11:32:40 +0100 Subject: [PATCH 104/129] Adding tests for reading and writing to/from ararys through points Disabling tests relating to reading pointers The fixes for reading pointers to arrays is not in this branch --- .../pointer_to_array_sensitivity_tests.c | 17 ++++++++- .../test.desc | 33 ++++++++++------- .../test.desc | 33 ++++++++++------- .../test.desc | 37 +++++++++++-------- 4 files changed, 78 insertions(+), 42 deletions(-) diff --git a/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c index b821af7a1f5..21afdf52054 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c @@ -7,8 +7,17 @@ int main(int argc, char *argv[]) int a[3]={1, 2, 3}; int *p=a; assert(p==&a[0]); + assert(*p==1); + assert(p[1]==2); + assert(1[p]==2); + + assert(*(p+1)==2); + assert(*(1+p)==2); + + assert(*(p-1)==1); + // Test pointer arithmetic int *q=&a[1]; assert(q==p+1); @@ -22,9 +31,15 @@ int main(int argc, char *argv[]) *q=4; assert(a[1]==4); - q[1]=5; + p[1]=5; assert(a[1]==5); + *(p+1)=6; + assert(a[1]==6); + + *(1+p)=7; + assert(a[1]==7); + a[1]=2; // We now explore pointers and indexes each with more than one possible value diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc index ac4e32cfc0f..12cd47f791f 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc @@ -5,18 +5,25 @@ sensitivity_test_constants_pointer_to_constants_array.c ^SIGNAL=0$ ^\[main.assertion.1\] .* assertion p==&a\[0\]: Success$ ^\[main.assertion.2\] .* assertion \*p==1: Success$ -^\[main.assertion.3\] .* assertion q==p\+1: Unknown$ -^\[main.assertion.4\] .* assertion \*q==2: Unknown$ -^\[main.assertion.5\] .* assertion q-p==x: Unknown$ -^\[main.assertion.6\] .* assertion a\[1\]==4: Unknown$ -^\[main.assertion.7\] .* assertion a\[1\]==5: Unknown$ -^\[main.assertion.8\] .* assertion \*r==2: Unknown$ -^\[main.assertion.9\] .* assertion \*r==1: Unknown$ -^\[main.assertion.10\] .* assertion \*s==0: Unknown$ -^\[main.assertion.11\] .* assertion \*s==1: Unknown$ -^\[main.assertion.12\] .* assertion t==p\+i: Unknown$ -^\[main.assertion.13\] .* assertion t-p==y: Unknown$ -^\[main.assertion.14\] .* assertion a\[i\]==5: Unknown$ -^\[main.assertion.15\] .* assertion a\[1\]==5: Unknown$ +^\[main\.assertion\.3\] .* assertion p\[1\]==2: Unknown$ +^\[main\.assertion\.4\] .* assertion 1\[p\]==2: Unknown$ +^\[main\.assertion\.5\] .* assertion \*\(p\+1\)==2: Unknown$ +^\[main\.assertion\.6\] .* assertion \*\(1\+p\)==2: Unknown$ +^\[main\.assertion\.7\] .* assertion \*\(p-1\)==1: Unknown$ +^\[main\.assertion\.8\] .* assertion q==p\+1: Unknown$ +^\[main\.assertion\.9\] .* assertion \*q==2: Unknown$ +^\[main\.assertion\.10\] .* assertion q-p==x: Unknown$ +^\[main\.assertion\.11\] .* assertion a\[1\]==4: Unknown$ +^\[main\.assertion\.12\] .* assertion a\[1\]==5: Unknown$ +^\[main\.assertion\.13\] .* assertion a\[1\]==6: Unknown$ +^\[main\.assertion\.14\] .* assertion a\[1\]==7: Unknown$ +^\[main\.assertion\.15\] .* assertion \*r==2: Unknown$ +^\[main\.assertion\.16\] .* assertion \*r==1: Unknown$ +^\[main\.assertion\.17\] .* assertion \*s==0: Unknown$ +^\[main\.assertion\.18\] .* assertion \*s==1: Unknown$ +^\[main\.assertion\.19\] .* assertion t==p\+i: Unknown$ +^\[main\.assertion\.20\] .* assertion t-p==y: Unknown$ +^\[main\.assertion\.21\] .* assertion a\[i\]==5: Unknown$ +^\[main\.assertion\.22\] .* assertion a\[1\]==5: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc index 77e34834024..4758432cea8 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc @@ -5,18 +5,25 @@ sensitivity_test_constants_pointer_to_two_value_array.c ^SIGNAL=0$ ^\[main.assertion.1\] .* assertion p==&a\[0\]: Success$ ^\[main.assertion.2\] .* assertion \*p==1: Unknown$ -^\[main.assertion.3\] .* assertion q==p\+1: Unknown$ -^\[main.assertion.4\] .* assertion \*q==2: Unknown$ -^\[main.assertion.5\] .* assertion q-p==x: Unknown$ -^\[main.assertion.6\] .* assertion a\[1\]==4: Unknown$ -^\[main.assertion.7\] .* assertion a\[1\]==5: Unknown$ -^\[main.assertion.8\] .* assertion \*r==2: Unknown$ -^\[main.assertion.9\] .* assertion \*r==1: Unknown$ -^\[main.assertion.10\] .* assertion \*s==0: Unknown$ -^\[main.assertion.11\] .* assertion \*s==1: Unknown$ -^\[main.assertion.12\] .* assertion t==p\+i: Unknown$ -^\[main.assertion.13\] .* assertion t-p==y: Unknown$ -^\[main.assertion.14\] .* assertion a\[i\]==5: Unknown$ -^\[main.assertion.15\] .* assertion a\[1\]==5: Unknown$ +^\[main\.assertion\.3\] .* assertion p\[1\]==2: Unknown$ +^\[main\.assertion\.4\] .* assertion 1\[p\]==2: Unknown$ +^\[main\.assertion\.5\] .* assertion \*\(p\+1\)==2: Unknown$ +^\[main\.assertion\.6\] .* assertion \*\(1\+p\)==2: Unknown$ +^\[main\.assertion\.7\] .* assertion \*\(p-1\)==1: Unknown$ +^\[main.assertion.8\] .* assertion q==p\+1: Unknown$ +^\[main.assertion.9\] .* assertion \*q==2: Unknown$ +^\[main.assertion.10\] .* assertion q-p==x: Unknown$ +^\[main.assertion.11\] .* assertion a\[1\]==4: Unknown$ +^\[main.assertion.12\] .* assertion a\[1\]==5: Unknown$ +^\[main\.assertion\.13\] .* assertion a\[1\]==6: Unknown$ +^\[main\.assertion\.14\] .* assertion a\[1\]==7: Unknown$ +^\[main.assertion.15\] .* assertion \*r==2: Unknown$ +^\[main.assertion.16\] .* assertion \*r==1: Unknown$ +^\[main.assertion.17\] .* assertion \*s==0: Unknown$ +^\[main.assertion.18\] .* assertion \*s==1: Unknown$ +^\[main.assertion.19\] .* assertion t==p\+i: Unknown$ +^\[main.assertion.20\] .* assertion t-p==y: Unknown$ +^\[main.assertion.21\] .* assertion a\[i\]==5: Unknown$ +^\[main.assertion.22\] .* assertion a\[1\]==5: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc index c4d829b7eea..b4af7c15ab1 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc @@ -3,20 +3,27 @@ sensitivity_test_two_value_pointer_to_two_value_array.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion p==&a\[0\]: Unknown$ -^\[main.assertion.2\] .* assertion \*p==1: Unknown$ -^\[main.assertion.3\] .* assertion q==p\+1: Unknown$ -^\[main.assertion.4\] .* assertion \*q==2: Unknown$ -^\[main.assertion.5\] .* assertion q-p==x: Unknown$ -^\[main.assertion.6\] .* assertion a\[1\]==4: Unknown$ -^\[main.assertion.7\] .* assertion a\[1\]==5: Unknown$ -^\[main.assertion.8\] .* assertion \*r==2: Unknown$ -^\[main.assertion.9\] .* assertion \*r==1: Unknown$ -^\[main.assertion.10\] .* assertion \*s==0: Unknown$ -^\[main.assertion.11\] .* assertion \*s==1: Unknown$ -^\[main.assertion.12\] .* assertion t==p\+i: Unknown$ -^\[main.assertion.13\] .* assertion t-p==y: Unknown$ -^\[main.assertion.14\] .* assertion a\[i\]==5: Unknown$ -^\[main.assertion.15\] .* assertion a\[1\]==5: Unknown$ +^\[main\.assertion\.1\] .* assertion p==&a\[0\]: Unknown$ +^\[main\.assertion\.2\] .* assertion \*p==1: Unknown$ +^\[main\.assertion\.3\] .* assertion p\[1\]==2: Unknown$ +^\[main\.assertion\.4\] .* assertion 1\[p\]==2: Unknown$ +^\[main\.assertion\.5\] .* assertion \*\(p\+1\)==2: Unknown$ +^\[main\.assertion\.6\] .* assertion \*\(1\+p\)==2: Unknown$ +^\[main\.assertion\.7\] .* assertion \*\(p-1\)==1: Unknown$ +^\[main\.assertion\.8\] .* assertion q==p\+1: Unknown$ +^\[main\.assertion\.9\] .* assertion \*q==2: Unknown$ +^\[main\.assertion\.10\] .* assertion q-p==x: Unknown$ +^\[main\.assertion\.11\] .* assertion a\[1\]==4: Unknown$ +^\[main\.assertion\.12\] .* assertion a\[1\]==5: Unknown$ +^\[main\.assertion\.13\] .* assertion a\[1\]==6: Unknown$ +^\[main\.assertion\.14\] .* assertion a\[1\]==7: Unknown$ +^\[main\.assertion\.15\] .* assertion \*r==2: Unknown$ +^\[main\.assertion\.16\] .* assertion \*r==1: Unknown$ +^\[main\.assertion\.17\] .* assertion \*s==0: Unknown$ +^\[main\.assertion\.18\] .* assertion \*s==1: Unknown$ +^\[main\.assertion\.19\] .* assertion t==p\+i: Unknown$ +^\[main\.assertion\.20\] .* assertion t-p==y: Unknown$ +^\[main\.assertion\.21\] .* assertion a\[i\]==5: Unknown$ +^\[main\.assertion\.22\] .* assertion a\[1\]==5: Unknown$ -- ^warning: ignoring From fdc1f82ba78b30a1e7ee33d0642cf31113de7bc3 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 11 Apr 2017 14:56:54 +0100 Subject: [PATCH 105/129] Fixed bug when doing a merge write to a pointer When a pointer was written through (using a dereference) but it was a merging write (e.g. when in an array), we were not assigning the new value back into the domain and the value was lost. Added this case to the array of pointers tests. For the two value array we get the wrong result for the final two assertions as we do not havoc the domain when writing to a pointer which we don't know what it points to. --- .../array_of_pointer_sensitivity_tests.c | 20 +++++++++++++++++++ .../test.desc | 4 ++++ .../test.desc | 4 ++++ .../test.desc | 4 ++++ .../constant_pointer_abstract_object.cpp | 4 +++- 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/regression/goto-analyzer/sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c index 907fc4180ad..b557202c3e5 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c @@ -152,5 +152,25 @@ int main(int argc, char *argv[]) assert(ek[0]==&ek0); assert(*ek[0]==60); + // Test writing to an unknown index (i.e. a merging write of the pointer) + int x = 4; + int y = 5; + int *ps[2] = {&x, &y}; + int i; + if(argc > 2) + { + i=0; + } + else + { + i=1; + } + *(ps[i])=4; + + assert(*ps[0]==4); + assert(*ps[1]==4); + assert(x==4); + assert(y==4); + return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc index a41d340d49d..23a01dec7f8 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc @@ -67,5 +67,9 @@ sensitivity_test_constants_array_of_constants_pointer.c ^\[main.assertion.62\] .* assertion \*ej\[2\]==51: Unknown$ ^\[main.assertion.63\] .* assertion ek\[0\]==&ek0: Unknown$ ^\[main.assertion.64\] .* assertion \*ek\[0\]==60: Unknown$ +^\[main\.assertion\.65\] .* assertion \*ps\[0\]==4: Success$ +^\[main\.assertion\.66\] .* assertion \*ps\[1\]==4: Unknown$ +^\[main\.assertion\.67\] .* assertion x==4: Success$ +^\[main\.assertion\.68\] .* assertion y==4: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc index 168bf25a428..51c41aff0a9 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc @@ -67,5 +67,9 @@ sensitivity_test_constants_array_of_two_value_pointer.c ^\[main.assertion.62\] .* assertion \*ej\[2\]==51: Unknown$ ^\[main.assertion.63\] .* assertion ek\[0\]==&ek0: Unknown$ ^\[main.assertion.64\] .* assertion \*ek\[0\]==60: Unknown$ +^\[main\.assertion\.65\] .* assertion \*ps\[0\]==4: Unknown$ +^\[main\.assertion\.66\] .* assertion \*ps\[1\]==4: Unknown$ +^\[main\.assertion\.67\] .* assertion x==4: Unknown$ +^\[main\.assertion\.68\] .* assertion y==4: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc index c4f68f9fd9a..d9267ab4c21 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc @@ -67,5 +67,9 @@ sensitivity_test_two_value_array_of_two_value_pointer.c ^\[main.assertion.62\] .* assertion \*ej\[2\]==51: Unknown$ ^\[main.assertion.63\] .* assertion ek\[0\]==&ek0: Unknown$ ^\[main.assertion.64\] .* assertion \*ek\[0\]==60: Unknown$ +^\[main\.assertion\.65\] .* assertion \*ps\[0\]==4: Unknown$ +^\[main\.assertion\.66\] .* assertion \*ps\[1\]==4: Unknown$ +^\[main\.assertion\.67\] .* assertion x==4: Success$ +^\[main\.assertion\.68\] .* assertion y==4: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index d45df364ab4..a3d0a1b0e6d 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -347,7 +347,9 @@ sharing_ptrt abstract_object_pointert pointed_value= environment.eval(address_expr.object(), ns); bool modifications; - pointed_value->merge(new_value, modifications); + abstract_object_pointert merged_value= + pointed_value->merge(new_value, modifications); + environment.assign(address_expr.object(), merged_value, ns); } else { From e3348063cf381ecd0fe6da806aa9f71983e258f6 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 21 Apr 2017 14:22:44 +0100 Subject: [PATCH 106/129] Reworked the double dispatch of the merge Rather than using a double dispatch hidden inside a macro in abstract_object, each object now handles the merge for the types that it supports. Made clone return a pointer to constant abstract object to ensure correct usage. --- .../abstract_enviroment.cpp | 7 +- .../variable-sensitivity/abstract_object.cpp | 71 +++++++++--------- .../variable-sensitivity/abstract_object.h | 72 ++++++------------- .../variable-sensitivity/abstract_value.h | 2 +- .../array_abstract_object.cpp | 3 +- .../array_abstract_object.h | 6 +- .../constant_abstract_value.cpp | 65 ++++++++++++++--- .../constant_abstract_value.h | 12 ++-- .../constant_array_abstract_object.cpp | 61 +++++++++++----- .../constant_array_abstract_object.h | 12 ++-- .../constant_pointer_abstract_object.cpp | 61 ++++++++++++---- .../constant_pointer_abstract_object.h | 11 ++- .../full_struct_abstract_object.cpp | 65 ++++++++++++----- .../full_struct_abstract_object.h | 12 ++-- .../pointer_abstract_object.cpp | 3 +- .../pointer_abstract_object.h | 6 +- .../struct_abstract_object.cpp | 3 +- .../struct_abstract_object.h | 6 +- 18 files changed, 295 insertions(+), 183 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index b28f4993c66..1961c560d63 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -564,8 +564,11 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) if(map.find(entry.first)!=map.end()) { bool object_modified=false; - abstract_object_pointert new_object=map[entry.first]->merge( - entry.second, object_modified); + abstract_object_pointert new_object= + abstract_objectt::merge( + map[entry.first], + entry.second, + object_modified); modified|=object_modified; map[entry.first]=new_object; diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 1b87ea3087b..3becde81b08 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -115,13 +115,12 @@ const typet &abstract_objectt::type() const /*******************************************************************\ -Function: abstract_objectt::merge_state +Function: abstract_objectt::merge Inputs: - op1 - the first abstract object - op2 - the second abstract object + other - The object to merge with this - Outputs: + Outputs: Returns true if the merge changed this value Purpose: Set this abstract object to be the result of merging two other abstract objects. This is the worst case - we can @@ -129,39 +128,16 @@ Function: abstract_objectt::merge_state \*******************************************************************/ -bool abstract_objectt::merge_state( - const abstract_object_pointert op1, const abstract_object_pointert op2) +bool abstract_objectt::merge(abstract_object_pointert other) { - top=op1->top || op2->top; - bottom=op1->bottom && op2->bottom; + abstract_object_pointert old=clone(); + top= old->top || other->top; + bottom=old->bottom && other->bottom; assert(!(top && bottom)); - return top!=op1->top || bottom!=op1->bottom; + return top!=old->top || bottom!=old->bottom; } -/*******************************************************************\ - -Function: abstract_objectt::merge - - Inputs: - op - the abstract object to merge with - - Outputs: - - Purpose: Set this abstract object to be the result of merging this - abstract object and the provided one. See merge_state. - -\*******************************************************************/ - -abstract_object_pointert abstract_objectt::merge( - const abstract_object_pointert op, bool &out_any_modifications) const -{ - assert(t==op->t); - internal_abstract_object_pointert m= - internal_abstract_object_pointert(new abstract_objectt(*this)); - out_any_modifications=m->merge_state(abstract_object_pointert(this), op); - return m; -} /*******************************************************************\ @@ -298,3 +274,34 @@ void abstract_objectt::output( out << "Unknown"; } } + +/*******************************************************************\ + +Function: abstract_objectt::merge + + Inputs: + op1 - the first abstract object to merge, this object determines + the sensitivity of the output and is the object compared against + to choose whether this merge changed anything + op2 - the second abstract object to merge + + Outputs: The merged abstract object with the same sensitivity as the + first parameter. out_modifications will be true if the resulting + abstract object is different from op1 + + Purpose: Clones the first parameter and merges it with the second. + + +\*******************************************************************/ + +abstract_object_pointert abstract_objectt::merge( + abstract_object_pointert op1, + abstract_object_pointert op2, + bool &out_modifications) +{ + internal_abstract_object_pointert result(op1->mutable_clone()); + out_modifications=result->merge(op2); + return result; +} + + diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index d59c1afc541..bee23f6c936 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -39,44 +39,13 @@ class namespacet; #define CLONE \ - virtual abstract_objectt* clone() const override \ + virtual internal_abstract_object_pointert mutable_clone() const override \ { \ typedef std::remove_const::type \ >::type current_typet; \ - return new current_typet(*this); \ + return internal_abstract_object_pointert(new current_typet(*this)); \ } \ -#define MERGE(parent_typet) \ - virtual abstract_object_pointert merge( \ - const abstract_object_pointert op, \ - bool &out_any_modifications) const override \ - {\ - assert(type()==op->type()); \ - typedef std::remove_const::type \ - >::type current_typet; \ - \ - /*Check the supplied parent type is indeed a parent*/ \ - static_assert(std::is_base_of::value, \ - "parent_typet in MERGE must be parent class of the current type"); \ - \ - typedef sharing_ptrt current_type_ptrt; \ - typedef internal_sharing_ptrt this_ptrt; \ - /* Cast the supplied type to the current type to */ \ - /* facilitate double dispatch*/ \ - current_type_ptrt n=std::dynamic_pointer_cast(op); \ - this_ptrt m=this_ptrt(new current_typet(*this)); \ - if(n!= NULL) \ - { \ - out_any_modifications= \ - m->merge_state(current_type_ptrt(new current_typet(*this)), n); \ - return m; \ - } \ - else \ - { \ - return parent_typet::merge( \ - abstract_object_pointert(op), out_any_modifications); \ - } \ - } \ /* Merge is designed to allow different abstractions to be merged * gracefully. There are two real use-cases for this: @@ -91,9 +60,9 @@ class namespacet; * a[i] = v * will cause this to happen. * - * To handle this, merge finds the most specific class that is a - * parent to both classes and generates a new object of that type. - * The actual state is then merged by merge_state. + * To handle this, merge is dispatched to the first abstract object being + * merged, which switches based on the type of the other object. If it can + * merge then it merges, otherwise it calls the parent merge. */ template @@ -116,12 +85,6 @@ class abstract_objectt virtual bool is_top() const; virtual bool is_bottom() const; - // This is both the interface and the base case of the recursion - // It uses merge state to produce a new object of the most - // specific common parent type and is thus copy-on-write safe. - virtual abstract_object_pointert merge( - const abstract_object_pointert op, bool &out_any_modifications) const; - // Interface for transforms abstract_object_pointert expression_transform( const exprt &expr, @@ -133,14 +96,16 @@ class abstract_objectt virtual void output( std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; - // Macro is not used as this does not override - virtual abstract_objectt* clone() const + abstract_object_pointert clone() const { - typedef std::remove_const::type - >::type current_typet; - return new current_typet(*this); + return mutable_clone(); } + static abstract_object_pointert merge( + abstract_object_pointert op1, + abstract_object_pointert op2, + bool &out_modifications); + private: // To enforce copy-on-write these are private and have read-only accessors typet t; @@ -152,14 +117,19 @@ class abstract_objectt typedef internal_sharing_ptrt internal_abstract_object_pointert; + // Macro is not used as this does not override + virtual internal_abstract_object_pointert mutable_clone() const + { + return internal_abstract_object_pointert(new abstract_objectt(*this)); + } + bool top; - // The one exception is merge_state in descendent classes, which needs this + // The one exception is merge in descendent classes, which needs this void make_top() { top=true; } // Sets the state of this object - bool merge_state( - const abstract_object_pointert op1, const abstract_object_pointert op2); + virtual bool merge(abstract_object_pointert other); template static bool merge_maps( @@ -215,7 +185,7 @@ bool abstract_objectt::merge_maps( bool changes=false; abstract_object_pointert v_new; - v_new=v1->merge(v2, changes); + v_new=abstract_objectt::merge(v1, v2, changes); modified|=changes; diff --git a/src/analyses/variable-sensitivity/abstract_value.h b/src/analyses/variable-sensitivity/abstract_value.h index c86f336bfb4..e7eb6eaf488 100644 --- a/src/analyses/variable-sensitivity/abstract_value.h +++ b/src/analyses/variable-sensitivity/abstract_value.h @@ -22,8 +22,8 @@ class abstract_valuet:public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); +protected: CLONE - MERGE(abstract_objectt) }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_VALUE_H diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 5b22bbd918d..18d6d325a2d 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -160,8 +160,7 @@ sharing_ptrt array_abstract_objectt::write_index( // havoc and the default should derive from this. if(is_top() || is_bottom()) { - return sharing_ptrt( - dynamic_cast(clone())); + return std::dynamic_pointer_cast(clone()); } else { diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index 50906a6f0fd..ae59c16588e 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -27,9 +27,6 @@ class array_abstract_objectt:public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - CLONE - MERGE(abstract_objectt) - virtual abstract_object_pointert read_index( const abstract_environmentt &env, const index_exprt &index, @@ -42,6 +39,9 @@ class array_abstract_objectt:public abstract_objectt const index_exprt &index_expr, const abstract_object_pointert value, bool merging_write) const; + +protected: + CLONE }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ARRAY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index 5e754549b1b..47fce253dfb 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -57,28 +57,71 @@ void constant_abstract_valuet::output( } } -bool constant_abstract_valuet::merge_state( - constant_abstract_value_pointert op1, - constant_abstract_value_pointert op2) +/*******************************************************************\ + +Function: constant_abstract_valuet::merge + + Inputs: + other - the abstract object to merge with + + Outputs: Returns true if this changes when performing this merge + + Purpose: Attempts to do a constant/constant merge if both are constants, + otherwise falls back to the parent merge + + +\*******************************************************************/ + +bool constant_abstract_valuet::merge(abstract_object_pointert other) +{ + constant_abstract_value_pointert cast_other= + std::dynamic_pointer_cast(other); + if(cast_other) + { + return merge_constant_constant(cast_other); + } + else + { + value=exprt(); + return abstract_valuet::merge(other); + } +} + +/*******************************************************************\ + +Function: constant_abstract_valuet::merge_constant_constant + + Inputs: + other - the abstract object to merge with + + Outputs: Returns true if this changes when performing this merge + + + Purpose: Merges another constant abstract value into this one + +\*******************************************************************/ + +bool constant_abstract_valuet::merge_constant_constant( + constant_abstract_value_pointert other) { - bool parent_merge_change=abstract_objectt::merge_state(op1, op2); + bool was_top=is_top(); + bool parent_merge_change=abstract_valuet::merge(other); + if(!is_top() && !is_bottom()) { - if(op1->value==op2->value) + if(value==other->value) { - value=op1->value; return false; } - else // values different + else { make_top(); - assert(is_bottom()==false); - // Clear out the expression + assert(!is_bottom()); value=exprt(); - return !op1->is_top(); + return !was_top; } } - else // either top or bottom + else { return parent_merge_change; } diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 4902203a2b6..f6550c41b79 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -28,9 +28,6 @@ class constant_abstract_valuet:public abstract_valuet const abstract_environmentt &environment, const namespacet &ns); - CLONE - MERGE(abstract_valuet) - virtual exprt to_constant() const override; virtual void output( @@ -38,12 +35,13 @@ class constant_abstract_valuet:public abstract_valuet const class ai_baset &ai, const class namespacet &ns) const override; -protected : - bool merge_state( - constant_abstract_value_pointert op1, - constant_abstract_value_pointert op2); +protected: + CLONE + virtual bool merge(abstract_object_pointert other) override; private : + bool merge_constant_constant(constant_abstract_value_pointert other); + exprt value; }; diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 1fadcee09fc..44258fe1cef 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -106,24 +106,53 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( /*******************************************************************\ -Function: constant_array_abstract_objectt::merge_state +Function: constant_array_abstract_objectt::merge Inputs: - op1 - The first array to merge - op2 - The second to merge + other - The object to merge in - Outputs: Returns true if the resulting abstract object is different to op1 + Outputs: Returns true if this merge changes this - Purpose: To modify this to be a merged version of op1 and op2, returning - true if the result is different to op1 + Purpose: Tries to do an array/array merge if merging with a constant array + If it can't, falls back to parent merge \*******************************************************************/ -bool constant_array_abstract_objectt::merge_state( - const constant_array_abstract_object_pointert op1, - const constant_array_abstract_object_pointert op2) +bool constant_array_abstract_objectt::merge( + abstract_object_pointert other) { - bool parent_merge_change=array_abstract_objectt::merge_state(op1, op2); + auto cast_other= + std::dynamic_pointer_cast(other); + if(cast_other) + { + return constant_array_merge(cast_other); + } + else + { + map.clear(); + return array_abstract_objectt::merge(other); + } +} + +/*******************************************************************\ + +Function: constant_array_abstract_objectt::constant_array_merge + + Inputs: + other - The object to merge in + + Outputs: Returns true if this merge changes this + + Purpose: Merges an array into this array + +\*******************************************************************/ + +bool constant_array_abstract_objectt::constant_array_merge( + const constant_array_abstract_object_pointert other) +{ + constant_array_abstract_object_pointert old= + std::dynamic_pointer_cast(clone()); + bool parent_merge_change=array_abstract_objectt::merge(other); if(is_top() || is_bottom()) { map.clear(); @@ -131,21 +160,21 @@ bool constant_array_abstract_objectt::merge_state( } else { - if(op1->is_bottom()) + if(old->is_bottom()) { - map=op2->map; + map=other->map; return true; } - if(op2->is_bottom()) + if(other->is_bottom()) { return false; } // Both not top or bottom - assert(!op1->is_top() && !op2->is_top()); - assert(!op1->is_bottom() && !op2->is_bottom()); + assert(!old->is_top() && !other->is_top()); + assert(!old->is_bottom() && !other->is_bottom()); - return abstract_objectt::merge_maps(op1->map, op2->map, map); + return abstract_objectt::merge_maps(old->map, other->map, map); } } diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index 99a61015c88..f3e2603295c 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -32,9 +32,6 @@ class constant_array_abstract_objectt:public array_abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - CLONE - MERGE(array_abstract_objectt) - void output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; @@ -52,9 +49,9 @@ class constant_array_abstract_objectt:public array_abstract_objectt bool merging_write) const override; protected: - bool merge_state( - const constant_array_abstract_object_pointert op1, - const constant_array_abstract_object_pointert op2); + CLONE + + virtual bool merge(abstract_object_pointert other) override; private: // Since we don't store for any index where the value is top @@ -71,6 +68,9 @@ class constant_array_abstract_objectt:public array_abstract_objectt abstract_object_pointert get_top_entry( const abstract_environmentt &env, const namespacet &ns) const; + + bool constant_array_merge( + const constant_array_abstract_object_pointert other); }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ARRAY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index a3d0a1b0e6d..37f039b4d0d 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -118,34 +118,65 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( /*******************************************************************\ -Function: constant_pointer_abstract_objectt::merge_state +Function: constant_pointer_abstract_objectt::merge Inputs: - op1 - the first pointer abstract object - op2 - the second pointer abstract object + other - the pointer being merged - Outputs: Returns true if this changed from op1 + Outputs: Returns true if this changed from this - Purpose: Set this abstract object to be the result of merging two - other abstract objects. This handles the case where if they are - both pointing to the same object we keep the value. + Purpose: Set this abstract object to be the result of merging this + abstract object. This calls the merge_constant_pointers if + we are trying to merge a constant pointer we use the constant pointer + constant pointer merge \*******************************************************************/ -bool constant_pointer_abstract_objectt::merge_state( - const constant_pointer_abstract_pointert op1, - const constant_pointer_abstract_pointert op2) +bool constant_pointer_abstract_objectt::merge(abstract_object_pointert other) { - bool parent_merge_change=abstract_objectt::merge_state(op1, op2); + auto cast_other= + std::dynamic_pointer_cast(other); + if(cast_other) + { + return merge_constant_pointers(cast_other); + } + else + { + value=nil_exprt(); + return pointer_abstract_objectt::merge(other); + } +} + +/*******************************************************************\ + +Function: constant_pointer_abstract_objectt::merge_constant_pointers + + Inputs: + other - the pointer being merged + + Outputs: Returns true if this changed from this + + Purpose: Merges two constant pointers. If they are pointing at the same + value, we merge, otherwise we set to top. + +\*******************************************************************/ + +bool constant_pointer_abstract_objectt::merge_constant_pointers( + const constant_pointer_abstract_pointert other) +{ + auto old= + std::dynamic_pointer_cast(clone()); + + bool parent_merge_change=abstract_objectt::merge(other); if(is_top() || is_bottom()) { + value=nil_exprt(); return parent_merge_change; } else { - if(op1->value==op2->value) + if(old->value==other->value) { - value=op1->value; return false; } else @@ -153,7 +184,7 @@ bool constant_pointer_abstract_objectt::merge_state( make_top(); value=nil_exprt(); assert(!is_bottom()); - return !op1->is_top(); + return !old->is_top(); } } } @@ -348,7 +379,7 @@ sharing_ptrt environment.eval(address_expr.object(), ns); bool modifications; abstract_object_pointert merged_value= - pointed_value->merge(new_value, modifications); + abstract_objectt::merge(pointed_value, new_value, modifications); environment.assign(address_expr.object(), merged_value, ns); } else diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 55b80538438..913a79308a7 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -33,9 +33,6 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - CLONE - MERGE(pointer_abstract_objectt) - exprt to_constant() const override; void output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; @@ -51,11 +48,13 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt bool merging_write) const override; protected: - bool merge_state( - const constant_pointer_abstract_pointert op1, - const constant_pointer_abstract_pointert op2); + virtual bool merge(abstract_object_pointert op1) override; + + CLONE private: + bool merge_constant_pointers(const constant_pointer_abstract_pointert other); + exprt value; }; diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 062c3ebb566..4980f9b0054 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -261,7 +261,7 @@ sharing_ptrt bool dummy; - it->second=it->second->merge(value, dummy); + it->second=abstract_objectt::merge(it->second, value, dummy); } else { @@ -334,51 +334,84 @@ bool full_struct_abstract_objectt::verify() const /*******************************************************************\ -Function: full_struct_abstract_objectt::merge_state +Function: full_struct_abstract_objectt::merge Inputs: + other - the other object being merged - Outputs: + Outputs: Returns true if this merge changes the value of this - Purpose: + Purpose: To merge an abstract object into this abstract object. If + the other is also a struct, we perform a constant_structs merge + Otherwise we call back to the parent merge. + +\*******************************************************************/ + +bool full_struct_abstract_objectt::merge(abstract_object_pointert other) +{ + constant_struct_pointert cast_other= + std::dynamic_pointer_cast(other); + if(cast_other) + { + return merge_constant_structs(cast_other); + } + else + { + map.clear(); + return struct_abstract_objectt::merge(other); + } +} + +/*******************************************************************\ + +Function: full_struct_abstract_objectt::merge_constant_structs + + Inputs: + other - the other object being merged + + Outputs: Returns true if this merge changes the value of this + + Purpose: Performs an element wise merge of the map for each struct \*******************************************************************/ -bool full_struct_abstract_objectt::merge_state( - const sharing_ptrt op1, - const sharing_ptrt op2) +bool full_struct_abstract_objectt::merge_constant_structs( + constant_struct_pointert other) { - bool changed; + auto old= + std::dynamic_pointer_cast(clone()); // consider top and bottom in parent - changed=abstract_objectt::merge_state(op1, op2); + bool parent_merge_change=abstract_objectt::merge(other); if(is_top() || is_bottom()) { map.clear(); assert(verify()); - return changed; + return parent_merge_change; } - assert(!op1->is_top() && !op2->is_top()); - assert(!op1->is_bottom() && !op2->is_bottom()); + assert(!old->is_top() && !other->is_top()); + assert(!old->is_bottom() && !other->is_bottom()); - if(op2->is_bottom()) + if(other->is_bottom()) { assert(verify()); return false; } - if(op1->is_bottom()) + if(old->is_bottom()) { - map=op2->map; + map=other->map; assert(verify()); return true; } // at this point both are different from top and bottom - return abstract_objectt::merge_maps(op1->map, op2->map, map); + bool merge_result= + abstract_objectt::merge_maps(old->map, other->map, map); assert(verify()); + return merge_result; } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 6caac30661a..7612aebc56b 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -31,8 +31,6 @@ class full_struct_abstract_objectt:public struct_abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - CLONE - MERGE(struct_abstract_objectt) // struct interface virtual abstract_object_pointert read_component( @@ -58,13 +56,17 @@ class full_struct_abstract_objectt:public struct_abstract_objectt typedef std::map struct_mapt; struct_mapt map; + typedef sharing_ptrt constant_struct_pointert; + + bool merge_constant_structs(constant_struct_pointert other); + protected: + CLONE + bool verify() const; // Set the state of this to the merge result of op1 and op2 and // return if the result is different from op1 - bool merge_state( - const sharing_ptrt op1, - const sharing_ptrt op2); + virtual bool merge(abstract_object_pointert other) override; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_FULL_STRUCT_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index 6609031df7d..1f6b2930ea5 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -154,8 +154,7 @@ sharing_ptrt if(is_top() || is_bottom()) { environment.havoc("Writing to a 2value pointer"); - return sharing_ptrt( - dynamic_cast(clone())); + return std::dynamic_pointer_cast(clone()); } else { diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index fb19d314a93..2b852b465e9 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -28,9 +28,6 @@ class pointer_abstract_objectt:public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - CLONE - MERGE(abstract_objectt) - // pointer interface virtual abstract_object_pointert read_dereference( const abstract_environmentt &env, const namespacet &ns) const; @@ -41,6 +38,9 @@ class pointer_abstract_objectt:public abstract_objectt const std::stack stack, const abstract_object_pointert value, bool merging_write) const; + +protected: + CLONE }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_POINTER_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index db98edce9f7..dfc7588b399 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -155,8 +155,7 @@ sharing_ptrt struct_abstract_objectt::write_component( { if(is_top() || is_bottom()) { - return sharing_ptrt( - dynamic_cast(clone())); + return std::dynamic_pointer_cast(clone()); } else { diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index 37a0a2f3340..0719d16c207 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -26,9 +26,6 @@ class struct_abstract_objectt:public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - CLONE - MERGE(abstract_objectt) - // struct interface virtual abstract_object_pointert read_component( const abstract_environmentt &environment, @@ -42,6 +39,9 @@ class struct_abstract_objectt:public abstract_objectt const member_exprt &member_expr, const abstract_object_pointert value, bool merging_write) const; + +protected: + CLONE }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H From be2a296c258bc140734f2ca6d3825af3bff83aa0 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 21 Apr 2017 14:27:29 +0100 Subject: [PATCH 107/129] Removing default copy constructors In all cases the copy constructor was doing what the default copy constructor would do. Remove to avoid confusion --- .../variable-sensitivity/abstract_object.cpp | 17 --------------- .../variable-sensitivity/abstract_object.h | 1 - .../variable-sensitivity/abstract_value.cpp | 17 --------------- .../variable-sensitivity/abstract_value.h | 1 - .../array_abstract_object.cpp | 18 ---------------- .../array_abstract_object.h | 1 - .../constant_abstract_value.cpp | 5 ----- .../constant_abstract_value.h | 1 - .../constant_array_abstract_object.cpp | 20 ------------------ .../constant_array_abstract_object.h | 1 - .../full_struct_abstract_object.cpp | 21 ------------------- .../full_struct_abstract_object.h | 2 -- .../pointer_abstract_object.cpp | 18 ---------------- .../pointer_abstract_object.h | 1 - .../struct_abstract_object.cpp | 18 ---------------- .../struct_abstract_object.h | 1 - 16 files changed, 143 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 3becde81b08..31fb3d45756 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -59,23 +59,6 @@ abstract_objectt::abstract_objectt(const typet &type, bool top, bool bottom): /*******************************************************************\ -Function: abstract_objectt::abstract_objectt - - Inputs: - old - the abstract object to copy from - - Outputs: - - Purpose: - -\*******************************************************************/ - -abstract_objectt::abstract_objectt(const abstract_objectt &old): - t(old.t), bottom(old.bottom), top(old.top) -{} - -/*******************************************************************\ - Function: abstract_objectt::abstract_objectt Inputs: diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index bee23f6c936..04f2f744fbd 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -75,7 +75,6 @@ class abstract_objectt public: explicit abstract_objectt(const typet &type); abstract_objectt(const typet &type, bool top, bool bottom); - abstract_objectt(const abstract_objectt &old); abstract_objectt( const exprt &expr, const abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/abstract_value.cpp b/src/analyses/variable-sensitivity/abstract_value.cpp index 812c3ef3662..6a2f75a8c55 100644 --- a/src/analyses/variable-sensitivity/abstract_value.cpp +++ b/src/analyses/variable-sensitivity/abstract_value.cpp @@ -52,23 +52,6 @@ abstract_valuet::abstract_valuet(const typet &type, bool top, bool bottom): /*******************************************************************\ -Function: abstract_valuet::abstract_valuet - - Inputs: - old - the abstract value to copy from - - Outputs: - - Purpose: - -\*******************************************************************/ - -abstract_valuet::abstract_valuet(const abstract_valuet &old): - abstract_objectt(old) -{} - -/*******************************************************************\ - Function: abstract_valuet::abstract_valuet Inputs: diff --git a/src/analyses/variable-sensitivity/abstract_value.h b/src/analyses/variable-sensitivity/abstract_value.h index e7eb6eaf488..6cf7163528f 100644 --- a/src/analyses/variable-sensitivity/abstract_value.h +++ b/src/analyses/variable-sensitivity/abstract_value.h @@ -16,7 +16,6 @@ class abstract_valuet:public abstract_objectt public: explicit abstract_valuet(const typet &type); abstract_valuet(const typet &type, bool top, bool bottom); - abstract_valuet(const abstract_valuet &old); abstract_valuet( const exprt &expr, const abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 18d6d325a2d..7e7d334cdac 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -56,24 +56,6 @@ array_abstract_objectt::array_abstract_objectt( /*******************************************************************\ -Function: array_abstract_objectt::array_abstract_objectt - - Inputs: - old - the abstract object to copy from - - Outputs: - - Purpose: - -\*******************************************************************/ - -array_abstract_objectt::array_abstract_objectt( - const array_abstract_objectt &old): - abstract_objectt(old) -{} - -/*******************************************************************\ - Function: array_abstract_objectt::array_abstract_objectt Inputs: diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index ae59c16588e..8bc29db4b2c 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -21,7 +21,6 @@ class array_abstract_objectt:public abstract_objectt public: explicit array_abstract_objectt(const typet &type); array_abstract_objectt(const typet &type, bool top, bool bottom); - explicit array_abstract_objectt(const array_abstract_objectt &old); explicit array_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index 47fce253dfb..968915eaff3 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -20,11 +20,6 @@ constant_abstract_valuet::constant_abstract_valuet(typet t, bool tp, bool bttm): abstract_valuet(t, tp, bttm), value() {} -constant_abstract_valuet::constant_abstract_valuet( - const constant_abstract_valuet &old): - abstract_valuet(old), value(old.value) -{} - constant_abstract_valuet::constant_abstract_valuet( const exprt e, const abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index f6550c41b79..7eed7e49676 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -22,7 +22,6 @@ class constant_abstract_valuet:public abstract_valuet public: explicit constant_abstract_valuet(typet t); constant_abstract_valuet(typet t, bool tp, bool bttm); - constant_abstract_valuet(const constant_abstract_valuet &old); constant_abstract_valuet( const exprt e, const abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 44258fe1cef..3fea6941c61 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -53,26 +53,6 @@ array_abstract_objectt(type, top, bottom) /*******************************************************************\ -Function: constant_array_abstract_objectt::constant_array_abstract_objectt - - Inputs: - old - the abstract object to copy from - - Outputs: - - Purpose: - -\*******************************************************************/ - -constant_array_abstract_objectt::constant_array_abstract_objectt( - const constant_array_abstract_objectt &old): - array_abstract_objectt(old) -{ - map=old.map; -} - -/*******************************************************************\ - Function: constant_array_abstract_objectt::constant_array_abstract_objectt Inputs: diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index f3e2603295c..0198e62c4b1 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -26,7 +26,6 @@ class constant_array_abstract_objectt:public array_abstract_objectt public: explicit constant_array_abstract_objectt(typet type); constant_array_abstract_objectt(typet type, bool top, bool bottom); - constant_array_abstract_objectt(const constant_array_abstract_objectt &old); constant_array_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 4980f9b0054..f892f6e7c35 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -66,27 +66,6 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( /*******************************************************************\ -Function: full_struct_abstract_objectt::full_struct_abstract_objectt - - Inputs: - old - the abstract object to copy from - - Outputs: - - Purpose: - -\*******************************************************************/ - -full_struct_abstract_objectt::full_struct_abstract_objectt( - const full_struct_abstract_objectt &old): - struct_abstract_objectt(old) -{ - map=old.map; - assert(verify()); -} - -/*******************************************************************\ - Function: full_struct_abstract_objectt::full_struct_abstract_objectt Inputs: diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 7612aebc56b..53bdf9d92c7 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -24,8 +24,6 @@ class full_struct_abstract_objectt:public struct_abstract_objectt full_struct_abstract_objectt(const typet &type, bool top, bool bottom); - explicit full_struct_abstract_objectt( - const full_struct_abstract_objectt &old); full_struct_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index 1f6b2930ea5..74790fb8dd5 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -57,24 +57,6 @@ pointer_abstract_objectt::pointer_abstract_objectt( /*******************************************************************\ -Function: pointer_abstract_objectt::pointer_abstract_objectt - - Inputs: - old - the abstract object to copy from - - Outputs: - - Purpose: - -\*******************************************************************/ - -pointer_abstract_objectt::pointer_abstract_objectt( - const pointer_abstract_objectt &old): - abstract_objectt(old) -{} - -/*******************************************************************\ - Function: pointer_abstract_objectt::pointer_abstract_objectt Inputs: diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index 2b852b465e9..26d0632214f 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -22,7 +22,6 @@ class pointer_abstract_objectt:public abstract_objectt public: explicit pointer_abstract_objectt(const typet &type); pointer_abstract_objectt(const typet &type, bool top, bool bottom); - explicit pointer_abstract_objectt(const pointer_abstract_objectt &old); explicit pointer_abstract_objectt( const exprt &e, const abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index dfc7588b399..e559e390be4 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -58,24 +58,6 @@ struct_abstract_objectt::struct_abstract_objectt( /*******************************************************************\ -Function: struct_abstract_objectt::struct_abstract_objectt - - Inputs: - old - the abstract object to copy from - - Outputs: - - Purpose: - -\*******************************************************************/ - -struct_abstract_objectt::struct_abstract_objectt( - const struct_abstract_objectt &old): - abstract_objectt(old) -{} - -/*******************************************************************\ - Function: struct_abstract_objectt::struct_abstract_objectt Inputs: diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index 0719d16c207..bbded930463 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -20,7 +20,6 @@ class struct_abstract_objectt:public abstract_objectt public: explicit struct_abstract_objectt(const typet &type); struct_abstract_objectt(const typet &type, bool top, bool bottom); - explicit struct_abstract_objectt(const struct_abstract_objectt &old); explicit struct_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, From d7260072319dd468ebfaafd1cb273cd9494e37b0 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 24 Apr 2017 15:17:31 +0100 Subject: [PATCH 108/129] Replacing map based switch statments with chained if/elses To improve readability, the map of lambdas is replaced with a chain of if else statements in both the eval and write methods. --- .../abstract_enviroment.cpp | 241 +++++++----------- 1 file changed, 93 insertions(+), 148 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 1961c560d63..d73ca2e185e 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -45,91 +45,71 @@ abstract_object_pointert abstract_environmentt::eval( if(bottom) return abstract_object_factory(expr.type(), ns, false, true); - typedef std::function eval_handlert; - std::map handlers= + // first try to canonicalise, including constant folding + const exprt &simplified_expr=simplify_expr(expr, ns); + + const irep_idt simplified_id=simplified_expr.id(); + if(simplified_id==ID_symbol) { + const symbol_exprt &symbol(to_symbol_expr(simplified_expr)); + const auto &symbol_entry=map.find(symbol); + if(symbol_entry==map.cend()) { - ID_symbol, [&](const exprt &expr) - { - const symbol_exprt &symbol(to_symbol_expr(expr)); - const auto &symbol_entry=map.find(symbol); - if(symbol_entry==map.cend()) - { - return abstract_object_factory(expr.type(), ns, true); - } - else - { - abstract_object_pointert found_symbol_value=symbol_entry->second; - return found_symbol_value; - } - } - }, - { - ID_constant, [&](const exprt &expr) - { - return abstract_object_factory( - expr.type(), to_constant_expr(expr), ns); - } - }, - { - ID_array, [&](const exprt &expr) - { - return abstract_object_factory( - expr.type(), expr, ns); - } - }, - { - ID_member, [&](const exprt &expr) - { - member_exprt member_expr(to_member_expr(expr)); - - sharing_ptrt struct_abstract_object= - std::dynamic_pointer_cast( - eval(member_expr.compound(), ns)); - - return struct_abstract_object->read_component(*this, member_expr, ns); - } - }, + return abstract_object_factory(simplified_expr.type(), ns, true); + } + else { - ID_address_of, [&](const exprt &expr) - { - sharing_ptrt pointer_object= - std::dynamic_pointer_cast( - abstract_object_factory(expr.type(), expr, ns)); + abstract_object_pointert found_symbol_value=symbol_entry->second; + return found_symbol_value; + } + } + else if(simplified_id==ID_member) + { + member_exprt member_expr(to_member_expr(simplified_expr)); - // Store the abstract object in the pointer - return pointer_object; - } - }, - { - ID_dereference, [&](const exprt &expr) - { - dereference_exprt dereference(to_dereference_expr(expr)); - sharing_ptrt pointer_abstract_object= - std::dynamic_pointer_cast( - eval(dereference.pointer(), ns)); + sharing_ptrt struct_abstract_object= + std::dynamic_pointer_cast( + eval(member_expr.compound(), ns)); - return pointer_abstract_object->read_dereference(*this, ns); - } - }, - { - ID_index, [&](const exprt &expr) - { - index_exprt index_expr(to_index_expr(expr)); - sharing_ptrt array_abstract_object= - std::dynamic_pointer_cast( - eval(index_expr.array(), ns)); + return struct_abstract_object->read_component(*this, member_expr, ns); + } + else if(simplified_id==ID_address_of) + { + sharing_ptrt pointer_object= + std::dynamic_pointer_cast( + abstract_object_factory(simplified_expr.type(), simplified_expr, ns)); - return array_abstract_object->read_index(*this, index_expr, ns); - } - } - }; + // Store the abstract object in the pointer + return pointer_object; + } + else if(simplified_id==ID_dereference) + { + dereference_exprt dereference(to_dereference_expr(simplified_expr)); + sharing_ptrt pointer_abstract_object= + std::dynamic_pointer_cast( + eval(dereference.pointer(), ns)); - // first try to canonicalise, including constant folding - const exprt &simplified_expr=simplify_expr(expr, ns); + return pointer_abstract_object->read_dereference(*this, ns); + } + else if(simplified_id==ID_index) + { + index_exprt index_expr(to_index_expr(simplified_expr)); + sharing_ptrt array_abstract_object= + std::dynamic_pointer_cast( + eval(index_expr.array(), ns)); - const auto &handler=handlers.find(simplified_expr.id()); - if(handler==handlers.cend()) + return array_abstract_object->read_index(*this, index_expr, ns); + } + else if(simplified_id==ID_array) + { + return abstract_object_factory(simplified_expr.type(), simplified_expr, ns); + } + else if(simplified_id==ID_constant) + { + return abstract_object_factory( + simplified_expr.type(), to_constant_expr(simplified_expr), ns); + } + else { // No special handling required by the abstract environment // delegate to the abstract object @@ -142,10 +122,6 @@ abstract_object_pointert abstract_environmentt::eval( return abstract_object_factory(simplified_expr.type(), ns, true); } } - else - { - return handler->second(simplified_expr); - } } /*******************************************************************\ @@ -309,12 +285,7 @@ abstract_object_pointert abstract_environmentt::write( const exprt & next_expr=remaining_stack.top(); remaining_stack.pop(); - typedef std::function< - abstract_object_pointert( - abstract_object_pointert, // The symbol we are modifying - std::stack, // The remaining stack - abstract_object_pointert)> // The value we are writing. - stacion_functiont; + const irep_idt &stack_head_id=next_expr.id(); // Each handler takes the abstract object referenced, copies it, // writes according to the type of expression (e.g. for ID_member) @@ -322,71 +293,45 @@ abstract_object_pointert abstract_environmentt::write( // write_member which will attempt to update the abstract object for the // relevant member. This modified abstract object is returned and this // is inserted back into the map - std::map handlers= + if(stack_head_id==ID_index) { - { - ID_index, [&]( - const abstract_object_pointert lhs_object, - std::stack stack, - abstract_object_pointert rhs_object) - { - sharing_ptrt array_abstract_object= - std::dynamic_pointer_cast(lhs_object); - - sharing_ptrt modified_array= - array_abstract_object->write_index( - *this, - ns, - stack, - to_index_expr(next_expr), - rhs_object, - merge_write); - - return modified_array; - } - }, - { - ID_member, [&]( - const abstract_object_pointert lhs_object, - std::stack stack, - abstract_object_pointert rhs_object) - { - sharing_ptrt struct_abstract_object= - std::dynamic_pointer_cast(lhs_object); - - sharing_ptrt modified_struct= - struct_abstract_object->write_component( - *this, - ns, - stack, - to_member_expr(next_expr), - rhs_object, - merge_write); - - return modified_struct; - } - }, - { - ID_dereference, [&]( - const abstract_object_pointert lhs_object, - std::stack stack, - abstract_object_pointert rhs_object) - { - sharing_ptrt pointer_abstract_object= - std::dynamic_pointer_cast(lhs_object); + sharing_ptrt array_abstract_object= + std::dynamic_pointer_cast(lhs); - sharing_ptrt modified_pointer= - pointer_abstract_object->write_dereference( - *this, ns, stack, rhs_object, merge_write); + sharing_ptrt modified_array= + array_abstract_object->write_index( + *this, ns, remaining_stack, to_index_expr(next_expr), rhs, merge_write); - return modified_pointer; - } - } - }; + return modified_array; + } + else if(stack_head_id==ID_member) + { + sharing_ptrt struct_abstract_object= + std::dynamic_pointer_cast(lhs); - // We added something to the stack that we couldn't deal with - assert(handlers.find(next_expr.id())!=handlers.end()); - return handlers[next_expr.id()](lhs, remaining_stack, rhs); + const member_exprt next_member_expr(to_member_expr(next_expr)); + sharing_ptrt modified_struct= + struct_abstract_object->write_component( + *this, ns, remaining_stack, next_member_expr, rhs, merge_write); + + return modified_struct; + } + else if(stack_head_id==ID_dereference) + { + sharing_ptrt pointer_abstract_object= + std::dynamic_pointer_cast(lhs); + + sharing_ptrt modified_pointer= + pointer_abstract_object->write_dereference( + *this, ns, remaining_stack, rhs, merge_write); + + return modified_pointer; + } + else + { + assert(0); + return nullptr; + } } /*******************************************************************\ From 2d055ea675ea7ac71bc3bd0fa9222812c570e798 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 24 Apr 2017 15:19:32 +0100 Subject: [PATCH 109/129] Explained why top must be used as the else clause in eval I attempted to change this to generating a abstract object directly from the simplified expression. This caused the tests to fail in what appeared to be a "better" way - that is the constant_propagator tests were reporting more assignment simplifications. Specifically, it was simplifying the return of the function to be a NONDET(int) rather than the return of the function. I've convinced the change is wrong and works by chance, if we could some how have exprt with no children but wasn't a symbol, but also wasn't really a constant, then this would be wrong. The optimisation is also probably wrong since if the return assignment happened earlier, the return value should be the same, not a new non-det. --- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index d73ca2e185e..b16e0602c69 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -119,6 +119,8 @@ abstract_object_pointert abstract_environmentt::eval( } else { + // It is important that this is top as the abstract object may not know + // how to handle the expression return abstract_object_factory(simplified_expr.type(), ns, true); } } From 7cf1446661c0da166a1d49d4ed0201d00e026bec Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 25 Apr 2017 10:21:26 +0100 Subject: [PATCH 110/129] Don't make copies unnecessarily when merging When we merge, we don't want to create a clone of the object if nothing changes as this reduces the ability of the sharing map to optimize. This simplifies the code for detecting whether a merge has changed anything, as we can compare the pointers, if they are pointing at the same thing, nothing has changed. It complicates the code for the merges as we need to be careful not to leak any abstract objects. We can't use the shared pointer wrapper as we want to be able to use the this pointer (unless we can use std::enable_shared_from_this?) --- .../variable-sensitivity/abstract_object.cpp | 43 +++++++--- .../variable-sensitivity/abstract_object.h | 16 ++-- .../variable-sensitivity/abstract_value.h | 2 + .../constant_abstract_value.cpp | 52 ++++++++---- .../constant_abstract_value.h | 7 +- .../constant_array_abstract_object.cpp | 71 ++++++++++------ .../constant_array_abstract_object.h | 9 +- .../constant_pointer_abstract_object.cpp | 60 +++++++++----- .../constant_pointer_abstract_object.h | 5 +- .../full_struct_abstract_object.cpp | 82 +++++++++++-------- .../full_struct_abstract_object.h | 4 +- 11 files changed, 224 insertions(+), 127 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 31fb3d45756..a2c2ae1258d 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -103,22 +103,31 @@ Function: abstract_objectt::merge Inputs: other - The object to merge with this - Outputs: Returns true if the merge changed this value + Outputs: Returns the result of the merge. - Purpose: Set this abstract object to be the result of merging two - other abstract objects. This is the worst case - we can - only set to top or bottom. + Purpose: Create a new abstract object that is the result of the merge, unless + the object would be unchanged, then would return itself. \*******************************************************************/ -bool abstract_objectt::merge(abstract_object_pointert other) +const abstract_objectt *abstract_objectt::merge( + abstract_object_pointert other) const { - abstract_object_pointert old=clone(); - top= old->top || other->top; - bottom=old->bottom && other->bottom; + if(top) + return this; + if(other->bottom) + return this; - assert(!(top && bottom)); - return top!=old->top || bottom!=old->bottom; + abstract_objectt *merged=mutable_clone(); + + // We are top if and only if the other is top (since this is not) + merged->top=other->top; + + // Other is definitely not bottom, so the merge definitely can't be bottom + merged->bottom=false; + + assert(!(merged->top && merged->bottom)); + return merged; } @@ -282,9 +291,17 @@ abstract_object_pointert abstract_objectt::merge( abstract_object_pointert op2, bool &out_modifications) { - internal_abstract_object_pointert result(op1->mutable_clone()); - out_modifications=result->merge(op2); - return result; + const abstract_objectt* result=op1->merge(op2); + // If no modifications, we will return the original pointer + out_modifications=result!=op1.get(); + if(!out_modifications) + { + return op1; + } + else + { + return abstract_object_pointert(result); + } } diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 04f2f744fbd..72bd659cf2f 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -39,11 +39,11 @@ class namespacet; #define CLONE \ - virtual internal_abstract_object_pointert mutable_clone() const override \ + virtual abstract_objectt *mutable_clone() const override \ { \ typedef std::remove_const::type \ >::type current_typet; \ - return internal_abstract_object_pointert(new current_typet(*this)); \ + return new current_typet(*this); \ } \ @@ -80,6 +80,8 @@ class abstract_objectt const abstract_environmentt &environment, const namespacet &ns); + virtual ~abstract_objectt() {} + const typet &type() const; virtual bool is_top() const; virtual bool is_bottom() const; @@ -97,7 +99,7 @@ class abstract_objectt abstract_object_pointert clone() const { - return mutable_clone(); + return abstract_object_pointert(mutable_clone()); } static abstract_object_pointert merge( @@ -117,18 +119,18 @@ class abstract_objectt internal_abstract_object_pointert; // Macro is not used as this does not override - virtual internal_abstract_object_pointert mutable_clone() const + virtual abstract_objectt *mutable_clone() const { - return internal_abstract_object_pointert(new abstract_objectt(*this)); + return new abstract_objectt(*this); } bool top; - // The one exception is merge in descendent classes, which needs this + // The one exception is merge in descendant classes, which needs this void make_top() { top=true; } // Sets the state of this object - virtual bool merge(abstract_object_pointert other); + virtual const abstract_objectt *merge(abstract_object_pointert other) const; template static bool merge_maps( diff --git a/src/analyses/variable-sensitivity/abstract_value.h b/src/analyses/variable-sensitivity/abstract_value.h index 6cf7163528f..6f4ab8374c0 100644 --- a/src/analyses/variable-sensitivity/abstract_value.h +++ b/src/analyses/variable-sensitivity/abstract_value.h @@ -21,6 +21,8 @@ class abstract_valuet:public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); + virtual ~abstract_valuet() {} + protected: CLONE }; diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index 968915eaff3..91ec744b9e7 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -59,7 +59,7 @@ Function: constant_abstract_valuet::merge Inputs: other - the abstract object to merge with - Outputs: Returns true if this changes when performing this merge + Outputs: Returns the result of the merge Purpose: Attempts to do a constant/constant merge if both are constants, otherwise falls back to the parent merge @@ -67,7 +67,8 @@ Function: constant_abstract_valuet::merge \*******************************************************************/ -bool constant_abstract_valuet::merge(abstract_object_pointert other) +const abstract_objectt *constant_abstract_valuet::merge( + abstract_object_pointert other) const { constant_abstract_value_pointert cast_other= std::dynamic_pointer_cast(other); @@ -77,7 +78,7 @@ bool constant_abstract_valuet::merge(abstract_object_pointert other) } else { - value=exprt(); + // TODO(tkiley): How do we set the result to be toppish? Does it matter? return abstract_valuet::merge(other); } } @@ -89,35 +90,54 @@ Function: constant_abstract_valuet::merge_constant_constant Inputs: other - the abstract object to merge with - Outputs: Returns true if this changes when performing this merge - + Outputs: Returns a new abstract object that is the result of the merge + unless the merge is the same as this abstract object, in which + case it returns this. Purpose: Merges another constant abstract value into this one \*******************************************************************/ -bool constant_abstract_valuet::merge_constant_constant( - constant_abstract_value_pointert other) +const abstract_objectt *constant_abstract_valuet::merge_constant_constant( + constant_abstract_value_pointert other) const { - bool was_top=is_top(); - bool parent_merge_change=abstract_valuet::merge(other); + const abstract_objectt *parent_merge=abstract_valuet::merge(other); - if(!is_top() && !is_bottom()) + // Did the parent merge result in a definitive result + if(!parent_merge->is_top() && !parent_merge->is_bottom()) { + // Can we actually merge these value if(value==other->value) { - return false; + // If the parent merge changed the merge, but we're neither top nor bottom + // then we can still return this + if(parent_merge!=this) + { + delete parent_merge; + parent_merge=nullptr; + } + return this; } else { - make_top(); - assert(!is_bottom()); - value=exprt(); - return !was_top; + // We need to make a new clone since the one created by the parent + // merge is immutable + if(parent_merge!=this) + { + delete parent_merge; + } + + constant_abstract_valuet *result= + static_cast(mutable_clone()); + + result->make_top(); + assert(!result->is_bottom()); + result->value=exprt(); + return result; } } else { - return parent_merge_change; + return parent_merge; } } diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 7eed7e49676..ef9b4a85824 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -27,6 +27,8 @@ class constant_abstract_valuet:public abstract_valuet const abstract_environmentt &environment, const namespacet &ns); + virtual ~constant_abstract_valuet() {} + virtual exprt to_constant() const override; virtual void output( @@ -36,10 +38,11 @@ class constant_abstract_valuet:public abstract_valuet protected: CLONE - virtual bool merge(abstract_object_pointert other) override; + virtual const abstract_objectt *merge(abstract_object_pointert other) const override; private : - bool merge_constant_constant(constant_abstract_value_pointert other); + const abstract_objectt *merge_constant_constant( + constant_abstract_value_pointert other) const; exprt value; }; diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 3fea6941c61..3776694bd13 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -91,15 +91,15 @@ Function: constant_array_abstract_objectt::merge Inputs: other - The object to merge in - Outputs: Returns true if this merge changes this + Outputs: Returns the result of the merge. Purpose: Tries to do an array/array merge if merging with a constant array If it can't, falls back to parent merge \*******************************************************************/ -bool constant_array_abstract_objectt::merge( - abstract_object_pointert other) +const abstract_objectt *constant_array_abstract_objectt::merge( + abstract_object_pointert other) const { auto cast_other= std::dynamic_pointer_cast(other); @@ -109,7 +109,7 @@ bool constant_array_abstract_objectt::merge( } else { - map.clear(); + // TODO(tkiley): How do we set the result to be toppish? Does it matter? return array_abstract_objectt::merge(other); } } @@ -121,40 +121,59 @@ Function: constant_array_abstract_objectt::constant_array_merge Inputs: other - The object to merge in - Outputs: Returns true if this merge changes this + Outputs: Returns a new abstract object that is the result of the merge + unless the merge is the same as this abstract object, in which + case it returns this.. Purpose: Merges an array into this array \*******************************************************************/ -bool constant_array_abstract_objectt::constant_array_merge( - const constant_array_abstract_object_pointert other) +const abstract_objectt *constant_array_abstract_objectt::constant_array_merge( + const constant_array_abstract_object_pointert other) const { - constant_array_abstract_object_pointert old= - std::dynamic_pointer_cast(clone()); - bool parent_merge_change=array_abstract_objectt::merge(other); - if(is_top() || is_bottom()) - { - map.clear(); - return parent_merge_change; - } - else + const abstract_objectt *parent_merge=array_abstract_objectt::merge(other); + + // Did the parent merge result in a definitive result + if(!parent_merge->is_top() && !parent_merge->is_bottom()) { - if(old->is_bottom()) + array_mapt merged_map; + bool modified= + abstract_objectt::merge_maps(map, other->map, merged_map); + // Can we actually merge these value + if(!modified) { - map=other->map; - return true; + // If the parent merge changed the merge, but we're neither top nor bottom + // then we can still return this + if(parent_merge!=this) + { + delete parent_merge; + parent_merge=nullptr; + } + return this; } - if(other->is_bottom()) + else { - return false; - } + // We need to make a new clone since the one created by the parent + // merge is immutable + if(parent_merge!=this) + { + delete parent_merge; + } + + constant_array_abstract_objectt *result= + dynamic_cast(mutable_clone()); - // Both not top or bottom - assert(!old->is_top() && !other->is_top()); - assert(!old->is_bottom() && !other->is_bottom()); + result->map=merged_map; - return abstract_objectt::merge_maps(old->map, other->map, map); + assert(!result->is_top()); + assert(!result->is_bottom()); + return result; + } + } + else + { + return parent_merge; } } diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index 0198e62c4b1..e76f2167d4f 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -31,6 +31,8 @@ class constant_array_abstract_objectt:public array_abstract_objectt const abstract_environmentt &environment, const namespacet &ns); + virtual ~constant_array_abstract_objectt() {} + void output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; @@ -50,7 +52,8 @@ class constant_array_abstract_objectt:public array_abstract_objectt protected: CLONE - virtual bool merge(abstract_object_pointert other) override; + virtual const abstract_objectt *merge( + abstract_object_pointert other) const override; private: // Since we don't store for any index where the value is top @@ -68,8 +71,8 @@ class constant_array_abstract_objectt:public array_abstract_objectt abstract_object_pointert get_top_entry( const abstract_environmentt &env, const namespacet &ns) const; - bool constant_array_merge( - const constant_array_abstract_object_pointert other); + const abstract_objectt *constant_array_merge( + const constant_array_abstract_object_pointert other) const; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ARRAY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 37f039b4d0d..54fad7ed708 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -123,7 +123,7 @@ Function: constant_pointer_abstract_objectt::merge Inputs: other - the pointer being merged - Outputs: Returns true if this changed from this + Outputs: Returns the result of the merge. Purpose: Set this abstract object to be the result of merging this abstract object. This calls the merge_constant_pointers if @@ -132,7 +132,8 @@ Function: constant_pointer_abstract_objectt::merge \*******************************************************************/ -bool constant_pointer_abstract_objectt::merge(abstract_object_pointert other) +const abstract_objectt *constant_pointer_abstract_objectt::merge( + abstract_object_pointert other) const { auto cast_other= std::dynamic_pointer_cast(other); @@ -142,7 +143,7 @@ bool constant_pointer_abstract_objectt::merge(abstract_object_pointert other) } else { - value=nil_exprt(); + // TODO(tkiley): How do we set the result to be toppish? return pointer_abstract_objectt::merge(other); } } @@ -154,39 +155,56 @@ Function: constant_pointer_abstract_objectt::merge_constant_pointers Inputs: other - the pointer being merged - Outputs: Returns true if this changed from this + Outputs: Returns a new abstract object that is the result of the merge + unless the merge is the same as this abstract object, in which + case it returns this. Purpose: Merges two constant pointers. If they are pointing at the same value, we merge, otherwise we set to top. \*******************************************************************/ -bool constant_pointer_abstract_objectt::merge_constant_pointers( - const constant_pointer_abstract_pointert other) +const abstract_objectt *constant_pointer_abstract_objectt::merge_constant_pointers( + const constant_pointer_abstract_pointert other) const { - auto old= - std::dynamic_pointer_cast(clone()); + const abstract_objectt *parent_merge=pointer_abstract_objectt::merge(other); - bool parent_merge_change=abstract_objectt::merge(other); - if(is_top() || is_bottom()) - { - value=nil_exprt(); - return parent_merge_change; - } - else + // Did the parent merge result in a definitive result + if(!parent_merge->is_top() && !parent_merge->is_bottom()) { - if(old->value==other->value) + if(value==other->value) { - return false; + // If the parent merge changed the merge, but we're neither top nor bottom + // then we can still return this + if(parent_merge!=this) + { + delete parent_merge; + parent_merge=nullptr; + } + return this; } else { - make_top(); - value=nil_exprt(); - assert(!is_bottom()); - return !old->is_top(); + // We need to make a new clone since the one created by the parent + // merge is immutable + if(parent_merge!=this) + { + delete parent_merge; + } + + constant_pointer_abstract_objectt *result= + static_cast(mutable_clone()); + + result->make_top(); + assert(!result->is_bottom()); + result->value=exprt(); + return result; } } + else + { + return parent_merge; + } } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 913a79308a7..66a313fdd1b 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -48,12 +48,13 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt bool merging_write) const override; protected: - virtual bool merge(abstract_object_pointert op1) override; + virtual const abstract_objectt *merge(abstract_object_pointert op1) const override; CLONE private: - bool merge_constant_pointers(const constant_pointer_abstract_pointert other); + const abstract_objectt *merge_constant_pointers( + const constant_pointer_abstract_pointert other) const; exprt value; }; diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index f892f6e7c35..e450a586c11 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -318,7 +318,7 @@ Function: full_struct_abstract_objectt::merge Inputs: other - the other object being merged - Outputs: Returns true if this merge changes the value of this + Outputs: Returns the result of the merge. Purpose: To merge an abstract object into this abstract object. If the other is also a struct, we perform a constant_structs merge @@ -326,7 +326,8 @@ Function: full_struct_abstract_objectt::merge \*******************************************************************/ -bool full_struct_abstract_objectt::merge(abstract_object_pointert other) +const abstract_objectt *full_struct_abstract_objectt::merge( + abstract_object_pointert other) const { constant_struct_pointert cast_other= std::dynamic_pointer_cast(other); @@ -336,7 +337,7 @@ bool full_struct_abstract_objectt::merge(abstract_object_pointert other) } else { - map.clear(); + // TODO(tkiley): How do we set the result to be toppish? Does it matter? return struct_abstract_objectt::merge(other); } } @@ -348,49 +349,60 @@ Function: full_struct_abstract_objectt::merge_constant_structs Inputs: other - the other object being merged - Outputs: Returns true if this merge changes the value of this + Outputs: Returns a new abstract object that is the result of the merge + unless the merge is the same as this abstract object, in which + case it returns this. Purpose: Performs an element wise merge of the map for each struct \*******************************************************************/ -bool full_struct_abstract_objectt::merge_constant_structs( - constant_struct_pointert other) +const abstract_objectt *full_struct_abstract_objectt::merge_constant_structs( + constant_struct_pointert other) const { - auto old= - std::dynamic_pointer_cast(clone()); + const abstract_objectt *parent_merge=struct_abstract_objectt::merge(other); - // consider top and bottom in parent - bool parent_merge_change=abstract_objectt::merge(other); - - if(is_top() || is_bottom()) + // Did the parent merge result in a definitive result + if(!parent_merge->is_top() && !parent_merge->is_bottom()) { - map.clear(); - assert(verify()); - return parent_merge_change; - } + struct_mapt merged_map; + bool modified= + abstract_objectt::merge_maps(map, other->map, merged_map); + // Can we actually merge these value + if(!modified) + { + // If the parent merge changed the merge, but we're neither top nor bottom + // then we can still return this + if(parent_merge!=this) + { + delete parent_merge; + parent_merge=nullptr; + } + assert(verify()); + return this; + } + else + { + // We need to make a new clone since the one created by the parent + // merge is immutable + if(parent_merge!=this) + { + delete parent_merge; + } - assert(!old->is_top() && !other->is_top()); - assert(!old->is_bottom() && !other->is_bottom()); + full_struct_abstract_objectt *result= + dynamic_cast(mutable_clone()); - if(other->is_bottom()) - { - assert(verify()); - return false; - } + result->map=merged_map; - if(old->is_bottom()) + assert(!result->is_top()); + assert(!result->is_bottom()); + assert(result->verify()); + return result; + } + } + else { - map=other->map; - assert(verify()); - return true; + return parent_merge; } - - - // at this point both are different from top and bottom - bool merge_result= - abstract_objectt::merge_maps(old->map, other->map, map); - - assert(verify()); - return merge_result; } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 53bdf9d92c7..89c36d0424e 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -56,7 +56,7 @@ class full_struct_abstract_objectt:public struct_abstract_objectt typedef sharing_ptrt constant_struct_pointert; - bool merge_constant_structs(constant_struct_pointert other); + const abstract_objectt *merge_constant_structs(constant_struct_pointert other) const; protected: CLONE @@ -64,7 +64,7 @@ class full_struct_abstract_objectt:public struct_abstract_objectt bool verify() const; // Set the state of this to the merge result of op1 and op2 and // return if the result is different from op1 - virtual bool merge(abstract_object_pointert other) override; + virtual const abstract_objectt *merge(abstract_object_pointert other) const override; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_FULL_STRUCT_ABSTRACT_OBJECT_H From 27723002fe6f1d01101d64edd79688469411235e Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 25 Apr 2017 11:28:00 +0100 Subject: [PATCH 111/129] Using enable_shared_from_this to eliminate naked pointers Modify the merge to return shared pointers by replacing returns of this with returns of `shared_from_this`. This simplifies the code for dealing with when need to modify the result in dervied classes as we are no longer responsible for freeing the pointer returned by the super class. --- .../variable-sensitivity/abstract_object.cpp | 21 +++++-------- .../variable-sensitivity/abstract_object.h | 12 ++++---- .../constant_abstract_value.cpp | 27 +++++------------ .../constant_abstract_value.h | 5 ++-- .../constant_array_abstract_object.cpp | 27 +++++------------ .../constant_array_abstract_object.h | 4 +-- .../constant_pointer_abstract_object.cpp | 30 ++++++------------- .../constant_pointer_abstract_object.h | 5 ++-- .../full_struct_abstract_object.cpp | 27 +++++------------ .../full_struct_abstract_object.h | 6 ++-- 10 files changed, 55 insertions(+), 109 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index a2c2ae1258d..cc527cbaa3f 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -110,15 +110,15 @@ Function: abstract_objectt::merge \*******************************************************************/ -const abstract_objectt *abstract_objectt::merge( +abstract_object_pointert abstract_objectt::merge( abstract_object_pointert other) const { if(top) - return this; + return shared_from_this(); if(other->bottom) - return this; + return shared_from_this(); - abstract_objectt *merged=mutable_clone(); + internal_abstract_object_pointert merged=mutable_clone(); // We are top if and only if the other is top (since this is not) merged->top=other->top; @@ -291,17 +291,10 @@ abstract_object_pointert abstract_objectt::merge( abstract_object_pointert op2, bool &out_modifications) { - const abstract_objectt* result=op1->merge(op2); + abstract_object_pointert result=op1->merge(op2); // If no modifications, we will return the original pointer - out_modifications=result!=op1.get(); - if(!out_modifications) - { - return op1; - } - else - { - return abstract_object_pointert(result); - } + out_modifications=result!=op1; + return result; } diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 72bd659cf2f..14833de89d1 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -39,11 +39,11 @@ class namespacet; #define CLONE \ - virtual abstract_objectt *mutable_clone() const override \ + virtual internal_abstract_object_pointert mutable_clone() const override \ { \ typedef std::remove_const::type \ >::type current_typet; \ - return new current_typet(*this); \ + return internal_abstract_object_pointert(new current_typet(*this)); \ } \ @@ -70,7 +70,7 @@ using sharing_ptrt=std::shared_ptr; // NOLINT(*) typedef sharing_ptrt abstract_object_pointert; -class abstract_objectt +class abstract_objectt:public std::enable_shared_from_this { public: explicit abstract_objectt(const typet &type); @@ -119,9 +119,9 @@ class abstract_objectt internal_abstract_object_pointert; // Macro is not used as this does not override - virtual abstract_objectt *mutable_clone() const + virtual internal_abstract_object_pointert mutable_clone() const { - return new abstract_objectt(*this); + return internal_abstract_object_pointert(new abstract_objectt(*this)); } bool top; @@ -130,7 +130,7 @@ class abstract_objectt void make_top() { top=true; } // Sets the state of this object - virtual const abstract_objectt *merge(abstract_object_pointert other) const; + virtual abstract_object_pointert merge(abstract_object_pointert other) const; template static bool merge_maps( diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index 91ec744b9e7..b345693e2e7 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -67,7 +67,7 @@ Function: constant_abstract_valuet::merge \*******************************************************************/ -const abstract_objectt *constant_abstract_valuet::merge( +abstract_object_pointert constant_abstract_valuet::merge( abstract_object_pointert other) const { constant_abstract_value_pointert cast_other= @@ -98,10 +98,10 @@ Function: constant_abstract_valuet::merge_constant_constant \*******************************************************************/ -const abstract_objectt *constant_abstract_valuet::merge_constant_constant( +abstract_object_pointert constant_abstract_valuet::merge_constant_constant( constant_abstract_value_pointert other) const { - const abstract_objectt *parent_merge=abstract_valuet::merge(other); + abstract_object_pointert parent_merge=abstract_valuet::merge(other); // Did the parent merge result in a definitive result if(!parent_merge->is_top() && !parent_merge->is_bottom()) @@ -109,26 +109,13 @@ const abstract_objectt *constant_abstract_valuet::merge_constant_constant( // Can we actually merge these value if(value==other->value) { - // If the parent merge changed the merge, but we're neither top nor bottom - // then we can still return this - if(parent_merge!=this) - { - delete parent_merge; - parent_merge=nullptr; - } - return this; + return shared_from_this(); } else { - // We need to make a new clone since the one created by the parent - // merge is immutable - if(parent_merge!=this) - { - delete parent_merge; - } - - constant_abstract_valuet *result= - static_cast(mutable_clone()); + internal_sharing_ptrt result= + std::dynamic_pointer_cast( + mutable_clone()); result->make_top(); assert(!result->is_bottom()); diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index ef9b4a85824..752b48734b4 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -38,10 +38,11 @@ class constant_abstract_valuet:public abstract_valuet protected: CLONE - virtual const abstract_objectt *merge(abstract_object_pointert other) const override; + virtual abstract_object_pointert merge( + abstract_object_pointert other) const override; private : - const abstract_objectt *merge_constant_constant( + abstract_object_pointert merge_constant_constant( constant_abstract_value_pointert other) const; exprt value; diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 3776694bd13..66274dd4e75 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -98,7 +98,7 @@ Function: constant_array_abstract_objectt::merge \*******************************************************************/ -const abstract_objectt *constant_array_abstract_objectt::merge( +abstract_object_pointert constant_array_abstract_objectt::merge( abstract_object_pointert other) const { auto cast_other= @@ -129,10 +129,10 @@ Function: constant_array_abstract_objectt::constant_array_merge \*******************************************************************/ -const abstract_objectt *constant_array_abstract_objectt::constant_array_merge( +abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( const constant_array_abstract_object_pointert other) const { - const abstract_objectt *parent_merge=array_abstract_objectt::merge(other); + abstract_object_pointert parent_merge=array_abstract_objectt::merge(other); // Did the parent merge result in a definitive result if(!parent_merge->is_top() && !parent_merge->is_bottom()) @@ -143,26 +143,13 @@ const abstract_objectt *constant_array_abstract_objectt::constant_array_merge( // Can we actually merge these value if(!modified) { - // If the parent merge changed the merge, but we're neither top nor bottom - // then we can still return this - if(parent_merge!=this) - { - delete parent_merge; - parent_merge=nullptr; - } - return this; + return shared_from_this(); } else { - // We need to make a new clone since the one created by the parent - // merge is immutable - if(parent_merge!=this) - { - delete parent_merge; - } - - constant_array_abstract_objectt *result= - dynamic_cast(mutable_clone()); + internal_sharing_ptrt result= + std::dynamic_pointer_cast( + mutable_clone()); result->map=merged_map; diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index e76f2167d4f..cc61815f417 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -52,7 +52,7 @@ class constant_array_abstract_objectt:public array_abstract_objectt protected: CLONE - virtual const abstract_objectt *merge( + virtual abstract_object_pointert merge( abstract_object_pointert other) const override; private: @@ -71,7 +71,7 @@ class constant_array_abstract_objectt:public array_abstract_objectt abstract_object_pointert get_top_entry( const abstract_environmentt &env, const namespacet &ns) const; - const abstract_objectt *constant_array_merge( + abstract_object_pointert constant_array_merge( const constant_array_abstract_object_pointert other) const; }; diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 54fad7ed708..4286c403996 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -132,7 +132,7 @@ Function: constant_pointer_abstract_objectt::merge \*******************************************************************/ -const abstract_objectt *constant_pointer_abstract_objectt::merge( +abstract_object_pointert constant_pointer_abstract_objectt::merge( abstract_object_pointert other) const { auto cast_other= @@ -164,36 +164,24 @@ Function: constant_pointer_abstract_objectt::merge_constant_pointers \*******************************************************************/ -const abstract_objectt *constant_pointer_abstract_objectt::merge_constant_pointers( - const constant_pointer_abstract_pointert other) const +abstract_object_pointert + constant_pointer_abstract_objectt::merge_constant_pointers( + const constant_pointer_abstract_pointert other) const { - const abstract_objectt *parent_merge=pointer_abstract_objectt::merge(other); + abstract_object_pointert parent_merge=pointer_abstract_objectt::merge(other); // Did the parent merge result in a definitive result if(!parent_merge->is_top() && !parent_merge->is_bottom()) { if(value==other->value) { - // If the parent merge changed the merge, but we're neither top nor bottom - // then we can still return this - if(parent_merge!=this) - { - delete parent_merge; - parent_merge=nullptr; - } - return this; + return shared_from_this(); } else { - // We need to make a new clone since the one created by the parent - // merge is immutable - if(parent_merge!=this) - { - delete parent_merge; - } - - constant_pointer_abstract_objectt *result= - static_cast(mutable_clone()); + internal_sharing_ptrt result= + std::dynamic_pointer_cast( + mutable_clone()); result->make_top(); assert(!result->is_bottom()); diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 66a313fdd1b..afdf1bddffc 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -48,12 +48,13 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt bool merging_write) const override; protected: - virtual const abstract_objectt *merge(abstract_object_pointert op1) const override; + virtual abstract_object_pointert merge( + abstract_object_pointert op1) const override; CLONE private: - const abstract_objectt *merge_constant_pointers( + abstract_object_pointert merge_constant_pointers( const constant_pointer_abstract_pointert other) const; exprt value; diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index e450a586c11..06c39acf57d 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -326,7 +326,7 @@ Function: full_struct_abstract_objectt::merge \*******************************************************************/ -const abstract_objectt *full_struct_abstract_objectt::merge( +abstract_object_pointert full_struct_abstract_objectt::merge( abstract_object_pointert other) const { constant_struct_pointert cast_other= @@ -357,10 +357,10 @@ Function: full_struct_abstract_objectt::merge_constant_structs \*******************************************************************/ -const abstract_objectt *full_struct_abstract_objectt::merge_constant_structs( +abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( constant_struct_pointert other) const { - const abstract_objectt *parent_merge=struct_abstract_objectt::merge(other); + abstract_object_pointert parent_merge=struct_abstract_objectt::merge(other); // Did the parent merge result in a definitive result if(!parent_merge->is_top() && !parent_merge->is_bottom()) @@ -371,27 +371,14 @@ const abstract_objectt *full_struct_abstract_objectt::merge_constant_structs( // Can we actually merge these value if(!modified) { - // If the parent merge changed the merge, but we're neither top nor bottom - // then we can still return this - if(parent_merge!=this) - { - delete parent_merge; - parent_merge=nullptr; - } assert(verify()); - return this; + return shared_from_this(); } else { - // We need to make a new clone since the one created by the parent - // merge is immutable - if(parent_merge!=this) - { - delete parent_merge; - } - - full_struct_abstract_objectt *result= - dynamic_cast(mutable_clone()); + internal_sharing_ptrt result= + std::dynamic_pointer_cast( + mutable_clone()); result->map=merged_map; diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 89c36d0424e..2e9edb3caac 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -56,7 +56,8 @@ class full_struct_abstract_objectt:public struct_abstract_objectt typedef sharing_ptrt constant_struct_pointert; - const abstract_objectt *merge_constant_structs(constant_struct_pointert other) const; + abstract_object_pointert merge_constant_structs( + constant_struct_pointert other) const; protected: CLONE @@ -64,7 +65,8 @@ class full_struct_abstract_objectt:public struct_abstract_objectt bool verify() const; // Set the state of this to the merge result of op1 and op2 and // return if the result is different from op1 - virtual const abstract_objectt *merge(abstract_object_pointert other) const override; + virtual abstract_object_pointert merge( + abstract_object_pointert other) const override; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_FULL_STRUCT_ABSTRACT_OBJECT_H From c84f11b16472e6f92a595acf94f4b7428d026ae6 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 25 Apr 2017 14:29:49 +0100 Subject: [PATCH 112/129] Adding unit tests for merging of abstract objects --- unit/Makefile | 1 + .../abstract_object/merge.cpp | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 unit/analyses/variable-sensitivity/abstract_object/merge.cpp diff --git a/unit/Makefile b/unit/Makefile index a1de1539ee7..6f270cd9b18 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -2,6 +2,7 @@ SRC = unit_tests.cpp \ catch_example.cpp \ + analyses/variable-sensitivity/abstract_object/merge.cpp \ # Empty last line INCLUDES= -I ../src/ -I. diff --git a/unit/analyses/variable-sensitivity/abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp new file mode 100644 index 00000000000..12def068bc1 --- /dev/null +++ b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp @@ -0,0 +1,98 @@ +/*******************************************************************\ + + Module: Unit tests for variable/sensitivity/abstract_object::merge + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +#include + +#include +#include + +TEST_CASE("merge_abstract_object", + "[core][analyses][variable-sensitivity][abstract_object][merge]") +{ + SECTION("abstract object merge with abstract object") + { + const typet object_type=signedbv_typet(32); + SECTION("merging top with...") + { + abstract_object_pointert op1= + std::make_shared(object_type, true, false); + + SECTION("top") + { + abstract_object_pointert op2= + std::make_shared(object_type, true, false); + + bool modifications; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modifications); + + // Simple correctness of merge + REQUIRE_FALSE(modifications); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + } + SECTION("bottom") + { + abstract_object_pointert op2= + std::make_shared(object_type, false, true); + + bool modifications; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modifications); + + // Simple correctness of merge + REQUIRE_FALSE(modifications); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + } + } + SECTION("merging bottom with...") + { + abstract_object_pointert op1= + std::make_shared(object_type, false, true); + + SECTION("top") + { + abstract_object_pointert op2= + std::make_shared(object_type, true, false); + + bool modifications; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modifications); + + // Simple correctness of merge + REQUIRE(modifications); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + } + SECTION("bottom") + { + abstract_object_pointert op2= + std::make_shared(object_type, false, true); + + bool modifications; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modifications); + + // Simple correctness of merge + REQUIRE_FALSE(modifications); + REQUIRE_FALSE(result->is_top()); + REQUIRE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + } + } + } +} From d8341af2d84fa0412f9d143d0274a2cb3397ca22 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 25 Apr 2017 17:36:58 +0100 Subject: [PATCH 113/129] Fixed bugs revealed by unit tests The base merge should always result in either top or bottom (it is up for dervied classes to clear the top flag if they are not top). Correctly use the base class merge when appropriate in merging constant values. --- .../variable-sensitivity/abstract_object.cpp | 9 ++----- .../constant_abstract_value.cpp | 26 +++++++------------ 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index cc527cbaa3f..2f59ec2219a 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -118,15 +118,10 @@ abstract_object_pointert abstract_objectt::merge( if(other->bottom) return shared_from_this(); - internal_abstract_object_pointert merged=mutable_clone(); - - // We are top if and only if the other is top (since this is not) - merged->top=other->top; - // Other is definitely not bottom, so the merge definitely can't be bottom + internal_abstract_object_pointert merged=mutable_clone(); + merged->top=true; merged->bottom=false; - - assert(!(merged->top && merged->bottom)); return merged; } diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index b345693e2e7..b38af463151 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -101,10 +101,15 @@ Function: constant_abstract_valuet::merge_constant_constant abstract_object_pointert constant_abstract_valuet::merge_constant_constant( constant_abstract_value_pointert other) const { - abstract_object_pointert parent_merge=abstract_valuet::merge(other); - - // Did the parent merge result in a definitive result - if(!parent_merge->is_top() && !parent_merge->is_bottom()) + if(is_top() || other->is_bottom()) + { + return abstract_valuet::merge(other); + } + else if(is_bottom()) + { + return std::make_shared(*other); + } + else { // Can we actually merge these value if(value==other->value) @@ -113,18 +118,7 @@ abstract_object_pointert constant_abstract_valuet::merge_constant_constant( } else { - internal_sharing_ptrt result= - std::dynamic_pointer_cast( - mutable_clone()); - - result->make_top(); - assert(!result->is_bottom()); - result->value=exprt(); - return result; + return abstract_valuet::merge(other); } } - else - { - return parent_merge; - } } From f90bf007c67fd8ac904101545f0a540b07c2d2cf Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 25 Apr 2017 17:37:45 +0100 Subject: [PATCH 114/129] Adding unit tests for constant abstract object. --- unit/Makefile | 1 + .../abstract_object/merge.cpp | 2 + .../constant_abstract_value/merge.cpp | 462 ++++++++++++++++++ 3 files changed, 465 insertions(+) create mode 100644 unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp diff --git a/unit/Makefile b/unit/Makefile index 6f270cd9b18..873fe9231e8 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -3,6 +3,7 @@ SRC = unit_tests.cpp \ catch_example.cpp \ analyses/variable-sensitivity/abstract_object/merge.cpp \ + analyses/variable-sensitivity/constant_abstract_value/merge.cpp \ # Empty last line INCLUDES= -I ../src/ -I. diff --git a/unit/analyses/variable-sensitivity/abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp index 12def068bc1..72f6085f501 100644 --- a/unit/analyses/variable-sensitivity/abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp @@ -75,6 +75,8 @@ TEST_CASE("merge_abstract_object", REQUIRE(modifications); REQUIRE(result->is_top()); REQUIRE_FALSE(result->is_bottom()); + + REQUIRE_FALSE(op1==result); } SECTION("bottom") { diff --git a/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp new file mode 100644 index 00000000000..3bf443c48d6 --- /dev/null +++ b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp @@ -0,0 +1,462 @@ +/*******************************************************************\ + + Module: Unit tests for constant_abstract_valuet::merge + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + + +// Debug printer for irept +std::ostream &operator<<(std::ostream &os, const irept &value) +{ + os << value.pretty(); + return os; +} + +TEST_CASE("merge_constant_abstract_value", + "[core][analyses][variable-sensitivity][constant_abstract_value][merge]") +{ + const exprt val1=constant_exprt::integer_constant(1); + const exprt val2=constant_exprt::integer_constant(2); + + abstract_environmentt enviroment; + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + abstract_object_pointert result; + bool modified; + + abstract_object_pointert op1; + abstract_object_pointert op2; + SECTION("constant AO merge with constant AO") + { + SECTION("merge value with...") + { + abstract_object_pointert op1= + std::make_shared(val1, enviroment, ns); + + SECTION("same value") + { + abstract_object_pointert op2= + std::make_shared(val1, enviroment, ns); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(cast_result->to_constant()==val1); + + // Is optimal + REQUIRE(result==op1); + } + SECTION("different value") + { + abstract_object_pointert op2= + std::make_shared(val2, enviroment, ns); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + + // We currently don't require the value has any reasonable value + + // Since it has modified, we definitely shouldn't be reusing the pointer + REQUIRE_FALSE(result==op1); + } + + SECTION("top") + { + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + + // We currently don't require the value has any reasonable value + + // Since it has modified, we definitely shouldn't be reusing the pointer + REQUIRE_FALSE(result==op1); + } + SECTION("bottom") + { + abstract_object_pointert op2= + std::make_shared(val1.type(), false, true); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(cast_result->to_constant()==val1); + + // Is optimal + REQUIRE(result==op1); + } + } + SECTION("merge top with") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), true, false); + + abstract_object_pointert op2; + SECTION("value") + { + op2=std::make_shared(val1, enviroment, ns); + + } + SECTION("top") + { + op2= + std::make_shared(val1.type(), true, false); + } + SECTION("bottom") + { + op2= + std::make_shared(val1.type(), false, true); + } + + // Whatever we are merging with, we should stay top + + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + } + SECTION("merge bottom with") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), false, true); + + abstract_object_pointert op2; + + SECTION("value") + { + op2= + std::make_shared(val1, enviroment, ns); + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE(modified); + REQUIRE_FALSE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + REQUIRE(result->to_constant()==val1); + + } + SECTION("top") + { + op2= + std::make_shared(val1.type(), true, false); + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + } + SECTION("bottom") + { + op2= + std::make_shared(val1.type(), false, true); + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(result->is_top()); + REQUIRE(result->is_bottom()); + + // Optimization correctness + REQUIRE(result==op1); + } + + // Whatever we are merging with, we should end up as them + + + + // We don't optimize for returning the second parameter if we can + } + } + SECTION("constant AO merge with AO") + { + SECTION("merge value with...") + { + abstract_object_pointert op1= + std::make_shared(val1, enviroment, ns); + + SECTION("top") + { + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + + // We currently don't require the value has any reasonable value + + // Since it has modified, we definitely shouldn't be reusing the pointer + REQUIRE_FALSE(result==op1); + } + SECTION("bottom") + { + abstract_object_pointert op2= + std::make_shared(val1.type(), false, true); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(cast_result->to_constant()==val1); + + // Is optimal + REQUIRE(result==op1); + } + } + SECTION("merge top with") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), true, false); + + SECTION("top") + { + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); + + // Whatever we are merging with, we should stay top + + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + + // Is type still correct + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + } + SECTION("bottom") + { + abstract_object_pointert op2= + std::make_shared(val1.type(), false, true); + + // Whatever we are merging with, we should stay top + + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + + // Is type still correct + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + } + } + SECTION("merge bottom with") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), false, true); + + SECTION("top") + { + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); + + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE(modified); + REQUIRE(result->is_top()==op2->is_top()); + REQUIRE(result->is_bottom()==op2->is_bottom()); + + // We don't optimize for returning the second parameter if we can + + // Is type still correct + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + } + SECTION("bottom") + { + abstract_object_pointert op2= + std::make_shared(val1.type(), false, true); + + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(result->is_top()); + REQUIRE(result->is_bottom()); + + // We don't optimize for returning the second parameter if we can + + // Is type still correct + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + } + } + } + SECTION("AO merge with constant AO") + { + SECTION("merge top with") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), true, false); + + SECTION("value") + { + abstract_object_pointert op2= + std::make_shared(val1, enviroment, ns); + + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + } + SECTION("top") + { + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); + + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + } + SECTION("bottom") + { + abstract_object_pointert op2= + std::make_shared(val1.type(), false, true); + + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + } + } + SECTION("merge bottom with") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), false, true); + + SECTION("value") + { + abstract_object_pointert op2= + std::make_shared(val1, enviroment, ns); + + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE(modified); + REQUIRE(typeid(result.get())==typeid(const abstract_objectt *)); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // We don't optimize for returning the second parameter if we can + } + SECTION("top") + { + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); + + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // We don't optimize for returning the second parameter if we can + } + SECTION("bottom") + { + abstract_object_pointert op2= + std::make_shared(val1.type(), false, true); + + result=abstract_objectt::merge(op1, op2, modified); + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(result->is_top()); + REQUIRE(result->is_bottom()); + + REQUIRE(result==op1); + } + } + } +} From b8a0c78c25d0ab8f519543c8789c5e2f3d67e294 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 27 Apr 2017 18:02:09 +0100 Subject: [PATCH 115/129] Adding tests for constant array Refactored the merge maps method to use std::intersection as there was a bug with empty maps caught by the unit tests. --- .../variable-sensitivity/abstract_object.h | 69 +++---- .../constant_array_abstract_object.cpp | 27 +-- .../constant_array_abstract_object.h | 3 +- .../variable_sensitivity_object_factory.cpp | 2 +- unit/Makefile | 1 + .../constant_array_abstract_object/merge.cpp | 168 ++++++++++++++++++ 6 files changed, 207 insertions(+), 63 deletions(-) create mode 100644 unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 14833de89d1..9b6d12f0588 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -149,62 +150,36 @@ bool abstract_objectt::merge_maps( typedef std::map abstract_object_mapt; - typename abstract_object_mapt::const_iterator it1=m1.begin(); - typename abstract_object_mapt::const_iterator it2=m2.begin(); - bool modified=false; - while(true) - { - if(it1->firstfirst) - { - // element of m1 is not in m2 - - it1++; - modified=true; - if(it1==m1.end()) - break; - } - else if(it2->firstfirst) - { - // element of m2 is not in m1 - - it2++; - if(it2==m2.end()) - { - modified=true; // as there is a remaining element in m1 - break; - } - } - else + std::vector> intersection_set; + std::set_intersection( + m1.cbegin(), + m1.cend(), + m2.cbegin(), + m2.cend(), + std::back_inserter(intersection_set), + []( + const std::pair &op1, + const std::pair &op2) { - // merge entries + return op1.first < op2.first; + }); - const abstract_object_pointert &v1=it1->second; - const abstract_object_pointert &v2=it2->second; - - bool changes=false; - abstract_object_pointert v_new; - - v_new=abstract_objectt::merge(v1, v2, changes); - - modified|=changes; + for(const typename abstract_object_mapt::value_type &entry : intersection_set) + { + // merge entries - out_map[it1->first]=v_new; + const abstract_object_pointert &v1=m1.at(entry.first); + const abstract_object_pointert &v2=m2.at(entry.first); - it1++; + bool changes=false; + abstract_object_pointert v_new=abstract_objectt::merge(v1, v2, changes); - if(it1==m1.end()) - break; - it2++; + modified|=changes; - if(it2==m2.end()) - { - modified=true; // as there is a remaining element in m1 - break; - } - } + out_map[entry.first]=v_new; } return modified; diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 66274dd4e75..98ce974538b 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -132,22 +133,26 @@ Function: constant_array_abstract_objectt::constant_array_merge abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( const constant_array_abstract_object_pointert other) const { - abstract_object_pointert parent_merge=array_abstract_objectt::merge(other); - - // Did the parent merge result in a definitive result - if(!parent_merge->is_top() && !parent_merge->is_bottom()) + if(is_top() || other->is_bottom()) + { + return array_abstract_objectt::merge(other); + } + else if(is_bottom()) + { + return std::make_shared(*other); + } + else { - array_mapt merged_map; + array_mapt merged_map=array_mapt(); bool modified= abstract_objectt::merge_maps(map, other->map, merged_map); - // Can we actually merge these value if(!modified) { return shared_from_this(); } else { - internal_sharing_ptrt result= + const auto &result= std::dynamic_pointer_cast( mutable_clone()); @@ -158,10 +163,6 @@ abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( return result; } } - else - { - return parent_merge; - } } /*******************************************************************\ @@ -403,8 +404,8 @@ bool constant_array_abstract_objectt::eval_index( if(value.is_constant()) { constant_exprt constant_index=to_constant_expr(value); - out_index=binary2integer(id2string(constant_index.get_value()), false); - return true; + bool result=to_integer(constant_index, out_index); + return !result; } else { diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index cc61815f417..7eb718788a9 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -19,11 +19,10 @@ class abstract_environmentt; class constant_array_abstract_objectt:public array_abstract_objectt { -private: +public: typedef sharing_ptrt const constant_array_abstract_object_pointert; -public: explicit constant_array_abstract_objectt(typet type); constant_array_abstract_objectt(typet type, bool top, bool bottom); constant_array_abstract_objectt( diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 444a40d259f..e68aeebee75 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -32,7 +32,7 @@ variable_sensitivity_object_factoryt::ABSTRACT_OBJECT_TYPET if(type.id()==ID_signedbv || type.id()==ID_unsignedbv || type.id()==ID_floatbv || type.id()==ID_fixedbv || - type.id()==ID_c_bool || type.id()==ID_bool) + type.id()==ID_c_bool || type.id()==ID_bool || type.id()==ID_integer) { abstract_object_type=CONSTANT; } diff --git a/unit/Makefile b/unit/Makefile index 873fe9231e8..8620ff3b37d 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -4,6 +4,7 @@ SRC = unit_tests.cpp \ catch_example.cpp \ analyses/variable-sensitivity/abstract_object/merge.cpp \ analyses/variable-sensitivity/constant_abstract_value/merge.cpp \ + analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp \ # Empty last line INCLUDES= -I ../src/ -I. diff --git a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp new file mode 100644 index 00000000000..6ab3e037ed2 --- /dev/null +++ b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp @@ -0,0 +1,168 @@ +/*******************************************************************\ + + Module: Unit tests for constant_array_abstract_object::merge + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +typedef constant_array_abstract_objectt::constant_array_abstract_object_pointert + constant_array_abstract_object_pointert; + +// Util + + +class array_utilt +{ +public: + array_utilt(const abstract_environmentt &enviroment, const namespacet &ns): + enviroment(enviroment), ns(ns) + {} + + exprt read_index( + constant_array_abstract_object_pointert array_object, + const index_exprt &index) const + { + return array_object->read_index(enviroment, index, ns)->to_constant(); + } + +private: + const abstract_environmentt &enviroment; + const namespacet ns; +}; + +TEST_CASE("merge_constant_array_abstract_object", + "[core]" + "[analyses][variable-sensitivity][constant_array_abstract_object][merge]") +{ + // int val1[3] = {1, 2, 3} + exprt val1= + array_exprt( + array_typet(integer_typet(), constant_exprt::integer_constant(3))); + val1.operands().push_back(constant_exprt::integer_constant(1)); + val1.operands().push_back(constant_exprt::integer_constant(2)); + val1.operands().push_back(constant_exprt::integer_constant(3)); + + // int val2[3] = {1, 4, 5} + exprt val2= + array_exprt( + array_typet(integer_typet(), constant_exprt::integer_constant(3))); + val2.operands().push_back(constant_exprt::integer_constant(1)); + val2.operands().push_back(constant_exprt::integer_constant(4)); + val2.operands().push_back(constant_exprt::integer_constant(5)); + + // index_exprt for reading from an array + const index_exprt i0= + index_exprt(nil_exprt(), constant_exprt::integer_constant(0)); + const index_exprt i1= + index_exprt(nil_exprt(), constant_exprt::integer_constant(1)); + const index_exprt i2= + index_exprt(nil_exprt(), constant_exprt::integer_constant(2)); + + abstract_environmentt enviroment; + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + optionst options; + options.set_option("pointers", true); + options.set_option("arrays", true); + options.set_option("structs", true); + variable_sensitivity_object_factoryt::instance().set_options(options); + + array_utilt util(enviroment, ns); + + abstract_object_pointert result; + bool modified=false; + + SECTION("constant array AO merge with constant array AO") + { + SECTION("merge array with...") + { + auto op1= + std::make_shared(val1, enviroment, ns); + + SECTION("same value") + { + INFO(val1.op0().type().id_string()); + + auto op2= + std::make_shared( + val1, enviroment, ns); + + REQUIRE(util.read_index(op1, i1)==val1.op1()); + REQUIRE(util.read_index(op1, i0)==val1.op0()); + + INFO(i2.pretty()); + + const exprt &arr_val2=util.read_index(op1, i2); + INFO(arr_val2.pretty()); + + REQUIRE(arr_val2==val1.op2()); + + REQUIRE(util.read_index(op2, i0)==val1.op0()); + REQUIRE(util.read_index(op2, i1)==val1.op1()); + REQUIRE(util.read_index(op2, i2)==val1.op2()); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast( + result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==val1.op0()); + REQUIRE(util.read_index(cast_result, i1)==val1.op1()); + REQUIRE(util.read_index(cast_result, i2)==val1.op2()); + + // Is optimal + REQUIRE(result==op1); + } + SECTION("different array") + { + abstract_object_pointert op2= + std::make_shared( + val2, enviroment, ns); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast( + result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==val1.op0()); + REQUIRE(util.read_index(cast_result, i1)==nil_exprt()); + REQUIRE(util.read_index(cast_result, i2)==nil_exprt()); + + + // Since it has modified, we definitely shouldn't be reusing the pointer + REQUIRE_FALSE(result==op1); + } + } + } +} From 3b05fe3b7ca10fc2927390e66c9c35fce4e5d54c Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 28 Apr 2017 11:47:52 +0100 Subject: [PATCH 116/129] Adding unit tests for the struct abstract object --- .../full_struct_abstract_object.h | 4 +- unit/Makefile | 1 + .../full_struct_abstract_object/merge.cpp | 200 ++++++++++++++++++ 3 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 2e9edb3caac..2c8794903ca 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -20,6 +20,8 @@ class member_exprt; class full_struct_abstract_objectt:public struct_abstract_objectt { public: + typedef sharing_ptrt constant_struct_pointert; + explicit full_struct_abstract_objectt(const typet &type); full_struct_abstract_objectt(const typet &type, bool top, bool bottom); @@ -54,7 +56,7 @@ class full_struct_abstract_objectt:public struct_abstract_objectt typedef std::map struct_mapt; struct_mapt map; - typedef sharing_ptrt constant_struct_pointert; + abstract_object_pointert merge_constant_structs( constant_struct_pointert other) const; diff --git a/unit/Makefile b/unit/Makefile index 8620ff3b37d..7f08c924554 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -5,6 +5,7 @@ SRC = unit_tests.cpp \ analyses/variable-sensitivity/abstract_object/merge.cpp \ analyses/variable-sensitivity/constant_abstract_value/merge.cpp \ analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp \ + analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp \ # Empty last line INCLUDES= -I ../src/ -I. diff --git a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp new file mode 100644 index 00000000000..bb7f5553393 --- /dev/null +++ b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp @@ -0,0 +1,200 @@ +/*******************************************************************\ + + Module: Unit tests for full_struct_abstract_object::merge + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +#include + +typedef constant_array_abstract_objectt::constant_array_abstract_object_pointert + constant_array_abstract_object_pointert; + +// Util + + +class struct_utilt +{ +public: + struct_utilt(abstract_environmentt &enviroment, const namespacet &ns): + enviroment(enviroment), ns(ns) + {} + + exprt read_component( + full_struct_abstract_objectt::constant_struct_pointert struct_object, + const member_exprt &component) const + { + return struct_object->read_component( + enviroment, component, ns)->to_constant(); + } + + // At the moment the full_struct_abstract_object does not support + // initialization directly from an exprt so we manually write the components + full_struct_abstract_objectt::constant_struct_pointert build_struct( + const struct_exprt &starting_value) + { + std::shared_ptr result= + std::make_shared( + starting_value, enviroment, ns); + + struct_typet struct_type(to_struct_type(starting_value.type())); + size_t comp_index=0; + for(const exprt &op : starting_value.operands()) + { + const auto &component=struct_type.components()[comp_index]; + std::shared_ptr new_result= + result->write_component( + enviroment, + ns, + std::stack(), + member_exprt(nil_exprt(), component.get_name()), + enviroment.eval(op, ns), + false); + result= + std::dynamic_pointer_cast( + new_result); + + ++comp_index; + } + + return result; + } + +private: + abstract_environmentt &enviroment; + const namespacet ns; +}; + +TEST_CASE("merge_full_struct_abstract_object", + "[core]" + "[analyses][variable-sensitivity][full_struct_abstract_object][merge]") +{ + // int val1[3] = {1, 2, 3} + struct_typet struct_type; + struct_union_typet::componentt comp_a("a", integer_typet()); + struct_union_typet::componentt comp_b("b", integer_typet()); + struct_union_typet::componentt comp_c("c", integer_typet()); + struct_type.components().push_back(comp_a); + struct_type.components().push_back(comp_b); + struct_type.components().push_back(comp_c); + + struct_exprt val1(struct_type); + val1.operands().push_back(constant_exprt::integer_constant(1)); + val1.operands().push_back(constant_exprt::integer_constant(2)); + val1.operands().push_back(constant_exprt::integer_constant(3)); + + // int val2[3] = {1, 4, 5} + struct_exprt val2(struct_type); + val2.operands().push_back(constant_exprt::integer_constant(1)); + val2.operands().push_back(constant_exprt::integer_constant(4)); + val2.operands().push_back(constant_exprt::integer_constant(5)); + + // index_exprt for reading from an array + const member_exprt a(nil_exprt(), "a"); + const member_exprt b(nil_exprt(), "b"); + const member_exprt c(nil_exprt(), "c"); + + abstract_environmentt enviroment; + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + optionst options; + options.set_option("pointers", true); + options.set_option("arrays", true); + options.set_option("structs", true); + variable_sensitivity_object_factoryt::instance().set_options(options); + + struct_utilt util(enviroment, ns); + + abstract_object_pointert result; + bool modified=false; + + SECTION("constant struct AO merge with constant struct AO") + { + SECTION("merge struct with...") + { + auto op1=util.build_struct(val1); + + SECTION("same value") + { + INFO(val1.op0().type().id_string()); + + auto op2=util.build_struct(val1); + + REQUIRE(util.read_component(op1, b)==val1.op1()); + REQUIRE(util.read_component(op1, a)==val1.op0()); + + INFO(c.pretty()); + + const exprt &arr_val2=util.read_component(op1, c); + INFO(arr_val2.pretty()); + + REQUIRE(arr_val2==val1.op2()); + + REQUIRE(util.read_component(op2, a)==val1.op0()); + REQUIRE(util.read_component(op2, b)==val1.op1()); + REQUIRE(util.read_component(op2, c)==val1.op2()); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast( + result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_component(cast_result, a)==val1.op0()); + REQUIRE(util.read_component(cast_result, b)==val1.op1()); + REQUIRE(util.read_component(cast_result, c)==val1.op2()); + + // Is optimal + REQUIRE(result==op1); + } + SECTION("different array") + { + abstract_object_pointert op2=util.build_struct(val2); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast( + result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_component(cast_result, a)==val1.op0()); + REQUIRE(util.read_component(cast_result, b)==nil_exprt()); + REQUIRE(util.read_component(cast_result, c)==nil_exprt()); + + + // Since it has modified, we definitely shouldn't be reusing the pointer + REQUIRE_FALSE(result==op1); + } + } + } +} From b2ef7386568af1e81b95f5a059f255ccd1ec186e Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 28 Apr 2017 11:49:57 +0100 Subject: [PATCH 117/129] Corrected merge methods for pointer and struct --- .../constant_pointer_abstract_object.cpp | 27 ++++++++----------- .../full_struct_abstract_object.cpp | 20 +++++++------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 4286c403996..e3f4ad2ea4c 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -168,31 +168,26 @@ abstract_object_pointert constant_pointer_abstract_objectt::merge_constant_pointers( const constant_pointer_abstract_pointert other) const { - abstract_object_pointert parent_merge=pointer_abstract_objectt::merge(other); - - // Did the parent merge result in a definitive result - if(!parent_merge->is_top() && !parent_merge->is_bottom()) + if(is_top() || other->is_bottom()) + { + return pointer_abstract_objectt::merge(other); + } + else if(is_bottom()) + { + return std::make_shared(*other); + } + else { + // Can we actually merge these value if(value==other->value) { return shared_from_this(); } else { - internal_sharing_ptrt result= - std::dynamic_pointer_cast( - mutable_clone()); - - result->make_top(); - assert(!result->is_bottom()); - result->value=exprt(); - return result; + return pointer_abstract_objectt::merge(other); } } - else - { - return parent_merge; - } } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 06c39acf57d..49a6b36ee05 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -360,15 +360,19 @@ Function: full_struct_abstract_objectt::merge_constant_structs abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( constant_struct_pointert other) const { - abstract_object_pointert parent_merge=struct_abstract_objectt::merge(other); - - // Did the parent merge result in a definitive result - if(!parent_merge->is_top() && !parent_merge->is_bottom()) + if(is_top() || other->is_bottom()) + { + return struct_abstract_objectt::merge(other); + } + else if(is_bottom()) + { + return std::make_shared(*other); + } + else { struct_mapt merged_map; bool modified= abstract_objectt::merge_maps(map, other->map, merged_map); - // Can we actually merge these value if(!modified) { assert(verify()); @@ -376,7 +380,7 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( } else { - internal_sharing_ptrt result= + const auto &result= std::dynamic_pointer_cast( mutable_clone()); @@ -388,8 +392,4 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( return result; } } - else - { - return parent_merge; - } } From c96f418f7331c81cff42c883b517f98d45146f58 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 28 Apr 2017 15:56:06 +0100 Subject: [PATCH 118/129] Rewriting the constant_abstract_value::merge using behaviour driven design --- .../constant_abstract_value/merge.cpp | 459 +++++++++++------- 1 file changed, 289 insertions(+), 170 deletions(-) diff --git a/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp index 3bf443c48d6..5572eaa33e0 100644 --- a/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp @@ -19,41 +19,39 @@ // Debug printer for irept std::ostream &operator<<(std::ostream &os, const irept &value) { - os << value.pretty(); - return os; + os << value.pretty(); + return os; } -TEST_CASE("merge_constant_abstract_value", +SCENARIO("merge_constant_abstract_value", "[core][analyses][variable-sensitivity][constant_abstract_value][merge]") { - const exprt val1=constant_exprt::integer_constant(1); - const exprt val2=constant_exprt::integer_constant(2); - - abstract_environmentt enviroment; - symbol_tablet symbol_table; - namespacet ns(symbol_table); + GIVEN("An environment with two values: 1 and 2") + { + const exprt val1=constant_exprt::integer_constant(1); + const exprt val2=constant_exprt::integer_constant(2); - abstract_object_pointert result; - bool modified; + abstract_environmentt enviroment; + symbol_tablet symbol_table; + namespacet ns(symbol_table); - abstract_object_pointert op1; - abstract_object_pointert op2; - SECTION("constant AO merge with constant AO") - { - SECTION("merge value with...") + WHEN("merging constant AO with value " + "with a constant AO with the same value") { abstract_object_pointert op1= std::make_shared(val1, enviroment, ns); + abstract_object_pointert op2= + std::make_shared(val1, enviroment, ns); - SECTION("same value") - { - abstract_object_pointert op2= - std::make_shared(val1, enviroment, ns); + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); - result=abstract_objectt::merge(op1, op2, modified); + const auto &cast_result= + std::dynamic_pointer_cast(result); - const auto &cast_result= - std::dynamic_pointer_cast(result); + THEN("The original abstract object should be returned unchanged") + { // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); @@ -63,18 +61,27 @@ TEST_CASE("merge_constant_abstract_value", REQUIRE_FALSE(cast_result->is_bottom()); REQUIRE(cast_result->to_constant()==val1); - // Is optimal + // Is optimal REQUIRE(result==op1); } - SECTION("different value") - { - abstract_object_pointert op2= - std::make_shared(val2, enviroment, ns); + } + WHEN("merging constant AO with value " + "with a constant AO with the different value") + { + abstract_object_pointert op1= + std::make_shared(val1, enviroment, ns); + abstract_object_pointert op2= + std::make_shared(val2, enviroment, ns); - result=abstract_objectt::merge(op1, op2, modified); + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= - std::dynamic_pointer_cast(result); + const auto &cast_result= + std::dynamic_pointer_cast(result); + + THEN("A new constant abstract object set to top should be returned") + { // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); @@ -87,17 +94,24 @@ TEST_CASE("merge_constant_abstract_value", // Since it has modified, we definitely shouldn't be reusing the pointer REQUIRE_FALSE(result==op1); - } + } + } + WHEN("merging constant AO with value with a constant AO set to top") + { + abstract_object_pointert op1= + std::make_shared(val1, enviroment, ns); + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); - SECTION("top") - { - abstract_object_pointert op2= - std::make_shared(val1.type(), true, false); + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); - result=abstract_objectt::merge(op1, op2, modified); + const auto &cast_result= + std::dynamic_pointer_cast(result); - const auto &cast_result= - std::dynamic_pointer_cast(result); + THEN("A new AO of the same type set to top ") + { // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); @@ -111,15 +125,23 @@ TEST_CASE("merge_constant_abstract_value", // Since it has modified, we definitely shouldn't be reusing the pointer REQUIRE_FALSE(result==op1); } - SECTION("bottom") - { - abstract_object_pointert op2= - std::make_shared(val1.type(), false, true); + } + WHEN("merging constant AO with value with a constant AO set to bottom") + { + abstract_object_pointert op1= + std::make_shared(val1, enviroment, ns); + abstract_object_pointert op2= + std::make_shared(val1.type(), false, true); - result=abstract_objectt::merge(op1, op2, modified); + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= - std::dynamic_pointer_cast(result); + const auto &cast_result= + std::dynamic_pointer_cast(result); + + THEN("The original AO should be returned") + { // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); @@ -133,73 +155,125 @@ TEST_CASE("merge_constant_abstract_value", REQUIRE(result==op1); } } - SECTION("merge top with") + WHEN("merging constant AO set to top with a constant AO with a value") { abstract_object_pointert op1= std::make_shared(val1.type(), true, false); - abstract_object_pointert op2; - SECTION("value") + abstract_object_pointert op2= + std::make_shared(val1, enviroment, ns); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + THEN("WE should return the same value") { - op2=std::make_shared(val1, enviroment, ns); + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + // Is optimal + REQUIRE(op1==result); } - SECTION("top") + } + WHEN("merging constant AO set to top with a constant AO set to top") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), true, false); + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + THEN("WE should return the same value") { - op2= - std::make_shared(val1.type(), true, false); + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); } - SECTION("bottom") - { - op2= + } + WHEN("merging constant AO set to top with a constant AO set to bottom") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), true, false); + abstract_object_pointert op2= std::make_shared(val1.type(), false, true); - } - // Whatever we are merging with, we should stay top + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); - result=abstract_objectt::merge(op1, op2, modified); - // Simple correctness of merge - REQUIRE_FALSE(modified); - REQUIRE(result->is_top()); - REQUIRE_FALSE(result->is_bottom()); + THEN("WE should return the same value") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); - // Is optimal - REQUIRE(op1==result); + // Is optimal + REQUIRE(op1==result); + } } - SECTION("merge bottom with") + WHEN("merging constant AO set to bottom with a constant AO with a value") { abstract_object_pointert op1= std::make_shared(val1.type(), false, true); + abstract_object_pointert op2= + std::make_shared(val1, enviroment, ns); - abstract_object_pointert op2; + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); - SECTION("value") + THEN("We should get an abstract object that has the same value as op2") { - op2= - std::make_shared(val1, enviroment, ns); - result=abstract_objectt::merge(op1, op2, modified); // Simple correctness of merge REQUIRE(modified); REQUIRE_FALSE(result->is_top()); REQUIRE_FALSE(result->is_bottom()); REQUIRE(result->to_constant()==val1); - } - SECTION("top") + } + WHEN("merging constant AO set to bottom with a constant AO set to top") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), false, true); + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + THEN("We should get a top abstract object back") { - op2= - std::make_shared(val1.type(), true, false); - result=abstract_objectt::merge(op1, op2, modified); // Simple correctness of merge REQUIRE(modified); REQUIRE(result->is_top()); REQUIRE_FALSE(result->is_bottom()); } - SECTION("bottom") + } + WHEN("merging constant AO set to bottom with a constant AO set to bottom") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), false, true); + abstract_object_pointert op2= + std::make_shared(val1.type(), false, true); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + THEN("We should get the same (bottom) AO back") { - op2= - std::make_shared(val1.type(), false, true); - result=abstract_objectt::merge(op1, op2, modified); // Simple correctness of merge REQUIRE_FALSE(modified); REQUIRE_FALSE(result->is_top()); @@ -208,30 +282,23 @@ TEST_CASE("merge_constant_abstract_value", // Optimization correctness REQUIRE(result==op1); } - - // Whatever we are merging with, we should end up as them - - - - // We don't optimize for returning the second parameter if we can } - } - SECTION("constant AO merge with AO") - { - SECTION("merge value with...") + WHEN("merging constant AO with value with a abstract object set to top") { abstract_object_pointert op1= std::make_shared(val1, enviroment, ns); + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); - SECTION("top") - { - abstract_object_pointert op2= - std::make_shared(val1.type(), true, false); + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); - result=abstract_objectt::merge(op1, op2, modified); + const auto &cast_result= + std::dynamic_pointer_cast(result); - const auto &cast_result= - std::dynamic_pointer_cast(result); + THEN("We should get a new AO of the same type but set to top") + { // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); @@ -245,15 +312,22 @@ TEST_CASE("merge_constant_abstract_value", // Since it has modified, we definitely shouldn't be reusing the pointer REQUIRE_FALSE(result==op1); } - SECTION("bottom") - { - abstract_object_pointert op2= - std::make_shared(val1.type(), false, true); + } + WHEN("merging constant AO with value with a abstract object set to bottom") + { + abstract_object_pointert op1= + std::make_shared(val1, enviroment, ns); + abstract_object_pointert op2= + std::make_shared(val1.type(), false, true); - result=abstract_objectt::merge(op1, op2, modified); + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= - std::dynamic_pointer_cast(result); + const auto &cast_result= + std::dynamic_pointer_cast(result); + THEN("We should get the same constant AO back") + { // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); @@ -267,19 +341,19 @@ TEST_CASE("merge_constant_abstract_value", REQUIRE(result==op1); } } - SECTION("merge top with") + WHEN("merging constant AO set to top with a abstract object set to top") { abstract_object_pointert op1= std::make_shared(val1.type(), true, false); + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); - SECTION("top") - { - abstract_object_pointert op2= - std::make_shared(val1.type(), true, false); - - // Whatever we are merging with, we should stay top + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); - result=abstract_objectt::merge(op1, op2, modified); + THEN("We should get the same abstract object back") + { // Simple correctness of merge REQUIRE_FALSE(modified); REQUIRE(result->is_top()); @@ -294,14 +368,19 @@ TEST_CASE("merge_constant_abstract_value", // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); } - SECTION("bottom") - { - abstract_object_pointert op2= - std::make_shared(val1.type(), false, true); - - // Whatever we are merging with, we should stay top + } + WHEN("merging constant AO set to top with a abstract object set to bottom") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), true, false); + abstract_object_pointert op2= + std::make_shared(val1.type(), false, true); - result=abstract_objectt::merge(op1, op2, modified); + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("Should get the same abstract object back") + { // Simple correctness of merge REQUIRE_FALSE(modified); REQUIRE(result->is_top()); @@ -317,21 +396,22 @@ TEST_CASE("merge_constant_abstract_value", REQUIRE(cast_result); } } - SECTION("merge bottom with") + WHEN("merging constant AO set to bottom with a abstract object set to top") { abstract_object_pointert op1= std::make_shared(val1.type(), false, true); + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); - SECTION("top") + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("Return a new top abstract object of the same type") { - abstract_object_pointert op2= - std::make_shared(val1.type(), true, false); - - result=abstract_objectt::merge(op1, op2, modified); // Simple correctness of merge REQUIRE(modified); - REQUIRE(result->is_top()==op2->is_top()); - REQUIRE(result->is_bottom()==op2->is_bottom()); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); // We don't optimize for returning the second parameter if we can @@ -341,18 +421,26 @@ TEST_CASE("merge_constant_abstract_value", // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); } - SECTION("bottom") - { - abstract_object_pointert op2= - std::make_shared(val1.type(), false, true); + } + WHEN("merging constant AO set to bottom with a AO set to bottom") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), false, true); + abstract_object_pointert op2= + std::make_shared(val1.type(), false, true); - result=abstract_objectt::merge(op1, op2, modified); + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("Return the original abstract object") + { // Simple correctness of merge REQUIRE_FALSE(modified); REQUIRE_FALSE(result->is_top()); REQUIRE(result->is_bottom()); - // We don't optimize for returning the second parameter if we can + // Optimization check + REQUIRE(result==op1); // Is type still correct const auto &cast_result= @@ -361,20 +449,19 @@ TEST_CASE("merge_constant_abstract_value", REQUIRE(cast_result); } } - } - SECTION("AO merge with constant AO") - { - SECTION("merge top with") + WHEN("merging AO set to top with a constant AO with a value") { abstract_object_pointert op1= std::make_shared(val1.type(), true, false); + abstract_object_pointert op2= + std::make_shared(val1, enviroment, ns); - SECTION("value") - { - abstract_object_pointert op2= - std::make_shared(val1, enviroment, ns); + bool modified; - result=abstract_objectt::merge(op1, op2, modified); + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("The original AO should be returned") + { // Simple correctness of merge REQUIRE_FALSE(modified); REQUIRE(result->is_top()); @@ -383,12 +470,19 @@ TEST_CASE("merge_constant_abstract_value", // Is optimal REQUIRE(op1==result); } - SECTION("top") - { - abstract_object_pointert op2= - std::make_shared(val1.type(), true, false); + } + WHEN("merging AO set to top with a constant AO set to top") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), true, false); + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); - result=abstract_objectt::merge(op1, op2, modified); + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("The original AO should be returned") + { // Simple correctness of merge REQUIRE_FALSE(modified); REQUIRE(result->is_top()); @@ -397,12 +491,19 @@ TEST_CASE("merge_constant_abstract_value", // Is optimal REQUIRE(op1==result); } - SECTION("bottom") - { - abstract_object_pointert op2= - std::make_shared(val1.type(), false, true); + } + WHEN("merging AO set to top with a constant AO set to bottom") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), true, false); + abstract_object_pointert op2= + std::make_shared(val1.type(), false, true); - result=abstract_objectt::merge(op1, op2, modified); + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("The original AO should be returned") + { // Simple correctness of merge REQUIRE_FALSE(modified); REQUIRE(result->is_top()); @@ -412,31 +513,41 @@ TEST_CASE("merge_constant_abstract_value", REQUIRE(op1==result); } } - SECTION("merge bottom with") + WHEN("merging AO set to bottom with a constant AO with a value") { abstract_object_pointert op1= std::make_shared(val1.type(), false, true); + abstract_object_pointert op2= + std::make_shared(val1, enviroment, ns); - SECTION("value") - { - abstract_object_pointert op2= - std::make_shared(val1, enviroment, ns); + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); - result=abstract_objectt::merge(op1, op2, modified); + THEN("The a new top AO should be returned") + { // Simple correctness of merge REQUIRE(modified); REQUIRE(typeid(result.get())==typeid(const abstract_objectt *)); REQUIRE(result->is_top()); REQUIRE_FALSE(result->is_bottom()); - - // We don't optimize for returning the second parameter if we can } - SECTION("top") - { - abstract_object_pointert op2= - std::make_shared(val1.type(), true, false); - result=abstract_objectt::merge(op1, op2, modified); + // We don't optimize for returning the second parameter if we can + } + WHEN("merging AO set to bottom with a constant AO set to top") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), false, true); + abstract_object_pointert op2= + std::make_shared(val1.type(), true, false); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + THEN("The a new top AO should be returned") + { // Simple correctness of merge REQUIRE(modified); REQUIRE(result->is_top()); @@ -444,12 +555,20 @@ TEST_CASE("merge_constant_abstract_value", // We don't optimize for returning the second parameter if we can } - SECTION("bottom") - { - abstract_object_pointert op2= - std::make_shared(val1.type(), false, true); + } + WHEN("merging AO set to bottom with a constant AO set to bottom") + { + abstract_object_pointert op1= + std::make_shared(val1.type(), false, true); + abstract_object_pointert op2= + std::make_shared(val1.type(), false, true); - result=abstract_objectt::merge(op1, op2, modified); + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + THEN("The original AO should be returned") + { // Simple correctness of merge REQUIRE_FALSE(modified); REQUIRE_FALSE(result->is_top()); From ca525bdf7b81b8f64d1afb95663c45f5743fa58f Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 2 May 2017 17:49:17 +0100 Subject: [PATCH 119/129] Replaced assert with __CPROVER_assert Use the CPROVER_assert as behaviour is consistent across platforms. --- .../constant_assertions_01/main.c | 10 +- .../constant_assertions_01/test.desc | 10 +- .../constant_assertions_02/main.c | 10 +- .../constant_assertions_02/test.desc | 10 +- .../constant_propagation_01/main.c | 2 +- .../constant_propagation_01/test.desc | 2 +- .../constant_propagation_02/main.c | 4 +- .../constant_propagation_03/main.c | 4 +- .../constant_propagation_04/main.c | 4 +- .../constant_propagation_05/main.c | 4 +- .../constant_propagation_05/test.desc | 2 +- .../constant_propagation_06/main.c | 4 +- .../constant_propagation_06/test.desc | 2 +- .../constant_propagation_07/main.c | 2 +- .../constant_propagation_08/main.c | 2 +- .../constant_propagation_09/main.c | 2 +- .../constant_propagation_10/main.c | 2 +- .../constant_propagation_10/test.desc | 2 +- .../constant_propagation_11/main.c | 2 +- .../constant_propagation_12/main.c | 2 +- .../constant_propagation_13/main.c | 2 +- .../constant_propagation_13/test.desc | 2 +- .../constant_propagation_14/main.c | 6 +- .../constant_propagation_14/test.desc | 4 +- .../constant_propagation_15/main.c | 2 +- .../constant_propagation_15/test.desc | 2 +- .../constant_propagation_17/main.c | 4 +- .../constant_propagation_17/test.desc | 2 +- regression/goto-analyzer/demo/main.c | 48 +++---- regression/goto-analyzer/intervals_01/main.c | 16 +-- .../goto-analyzer/intervals_01/test.desc | 16 +-- regression/goto-analyzer/intervals_02/main.c | 2 +- regression/goto-analyzer/intervals_03/main.c | 2 +- regression/goto-analyzer/intervals_04/main.c | 2 +- regression/goto-analyzer/intervals_05/main.c | 2 +- regression/goto-analyzer/intervals_06/main.c | 2 +- regression/goto-analyzer/intervals_07/main.c | 2 +- regression/goto-analyzer/intervals_08/main.c | 2 +- regression/goto-analyzer/intervals_09/main.c | 8 +- regression/goto-analyzer/intervals_10/main.c | 10 +- regression/goto-analyzer/intervals_11/main.c | 6 +- regression/goto-analyzer/intervals_12/main.c | 4 +- regression/goto-analyzer/intervals_13/main.c | 16 +-- .../goto-analyzer/intervals_13/test.desc | 16 +-- regression/goto-analyzer/intervals_14/main.c | 8 +- regression/goto-analyzer/intervals_15/main.c | 4 +- .../goto-analyzer/intervals_15/test.desc | 2 +- regression/goto-analyzer/intervals_16/main.c | 4 +- .../goto-analyzer/intervals_16/test.desc | 2 +- .../minimal_reproducer_for_struct_problem.c | 16 +-- .../test.desc | 16 +-- .../array_of_array_sensitivity_tests.c | 132 ++++++++--------- .../array_of_pointer_sensitivity_tests.c | 136 +++++++++--------- .../array_sensitivity_tests.c | 64 ++++----- .../char_sensitivity_tests.c | 4 +- .../float_sensitivity_tests.c | 4 +- .../int_sensitivity_tests.c | 56 ++++---- .../pointer_sensitivity_tests.c | 28 ++-- .../pointer_to_array_sensitivity_tests.c | 44 +++--- .../pointer_to_pointer_sensitivity_tests.c | 12 +- .../pointer_to_struct_sensitivity_tests.c | 12 +- .../struct_of_array_sensitivity_tests.c | 34 ++--- .../struct_of_pointer_sensitivity_tests.c | 52 +++---- .../struct_of_struct_sensitivity_tests.c | 22 +-- .../struct_sensitivity_tests.c | 18 +-- .../test.desc | 132 ++++++++--------- .../test.desc | 136 +++++++++--------- .../test.desc | 136 +++++++++--------- .../test.desc | 64 ++++----- .../sensitivity-test-constants-char/test.desc | 4 +- .../test.desc | 4 +- .../sensitivity-test-constants-int/test.desc | 56 ++++---- .../test.desc | 44 +++--- .../test.desc | 12 +- .../test.desc | 12 +- .../test.desc | 44 +++--- .../test.desc | 12 +- .../test.desc | 28 ++-- .../test.desc | 34 ++--- .../test.desc | 52 +++---- .../test.desc | 22 +-- .../test.desc | 34 ++--- .../test.desc | 52 +++---- .../test.desc | 18 +-- .../test.desc | 132 ++++++++--------- .../test.desc | 136 +++++++++--------- .../test.desc | 64 ++++----- .../test.desc | 44 +++--- .../test.desc | 12 +- .../test.desc | 12 +- .../test.desc | 28 ++-- .../test.desc | 34 ++--- .../test.desc | 52 +++---- .../test.desc | 22 +-- .../test.desc | 18 +-- .../unreachable_assertions_01/main.c | 10 +- .../unreachable_assertions_01/test.desc | 10 +- 97 files changed, 1200 insertions(+), 1200 deletions(-) diff --git a/regression/goto-analyzer/constant_assertions_01/main.c b/regression/goto-analyzer/constant_assertions_01/main.c index 6cc8b8a6054..3a767276c2a 100644 --- a/regression/goto-analyzer/constant_assertions_01/main.c +++ b/regression/goto-analyzer/constant_assertions_01/main.c @@ -7,11 +7,11 @@ int main (int argc, char **argv) int x = nondet_int(); int y = nondet_int(); - assert(0); - assert(0 && 1); - assert(0 || 0); - assert(0 && x); - assert(y && 0); + __CPROVER_assert(0, "0"); + __CPROVER_assert(0 && 1, "0 && 1"); + __CPROVER_assert(0 || 0, "0 || 0"); + __CPROVER_assert(0 && x, "0 && x"); + __CPROVER_assert(y && 0, "y && 0"); return 0; } diff --git a/regression/goto-analyzer/constant_assertions_01/test.desc b/regression/goto-analyzer/constant_assertions_01/test.desc index f01bcf15bba..51b45717a62 100644 --- a/regression/goto-analyzer/constant_assertions_01/test.desc +++ b/regression/goto-analyzer/constant_assertions_01/test.desc @@ -1,11 +1,11 @@ CORE main.c --verify --variable -^\[main.assertion.1\] file main.c .* assertion 0: Failure \(if reachable\)$ -^\[main.assertion.2\] file main.c .* assertion 0 && 1: Failure \(if reachable\)$ -^\[main.assertion.3\] file main.c .* assertion 0 || 0: Failure \(if reachable\)$ -^\[main.assertion.4\] file main.c .* assertion 0 && x: Failure \(if reachable\)$ -^\[main.assertion.5\] file main.c .* assertion y && 0: Failure \(if reachable\)$ +^\[main.assertion.1\] file main.c .* 0: Failure \(if reachable\)$ +^\[main.assertion.2\] file main.c .* 0 && 1: Failure \(if reachable\)$ +^\[main.assertion.3\] file main.c .* 0 || 0: Failure \(if reachable\)$ +^\[main.assertion.4\] file main.c .* 0 && x: Failure \(if reachable\)$ +^\[main.assertion.5\] file main.c .* y && 0: Failure \(if reachable\)$ ^EXIT=0$ ^SIGNAL=0$ -- diff --git a/regression/goto-analyzer/constant_assertions_02/main.c b/regression/goto-analyzer/constant_assertions_02/main.c index e937622ad2b..889d980d200 100644 --- a/regression/goto-analyzer/constant_assertions_02/main.c +++ b/regression/goto-analyzer/constant_assertions_02/main.c @@ -7,11 +7,11 @@ int main (int argc, char **argv) int x = nondet_int(); int y = nondet_int(); - assert(1); - assert(0 || 1); - assert(1 && 1); - assert(1 || x); - assert(y || 1); + __CPROVER_assert(1, "1"); + __CPROVER_assert(0 || 1, "0 || 1"); + __CPROVER_assert(1 && 1, "1 && 1"); + __CPROVER_assert(1 || x, "1 || x"); + __CPROVER_assert(y || 1, "y || 1"); return 0; } diff --git a/regression/goto-analyzer/constant_assertions_02/test.desc b/regression/goto-analyzer/constant_assertions_02/test.desc index b5fad36b1ad..577ec981fd2 100644 --- a/regression/goto-analyzer/constant_assertions_02/test.desc +++ b/regression/goto-analyzer/constant_assertions_02/test.desc @@ -1,11 +1,11 @@ CORE main.c --verify --variable -^\[main\.assertion\.1\] file main\.c .* assertion 1: Success -^\[main\.assertion\.2\] file main\.c .* assertion 0 || 1: Success -^\[main\.assertion\.3\] file main\.c .* assertion 1 && 1: Success -^\[main\.assertion\.4\] file main\.c .* assertion 1 || x: Success -^\[main\.assertion\.5\] file main\.c .* assertion y || 1: Success +^\[main\.assertion\.1\] file main\.c .* 1: Success +^\[main\.assertion\.2\] file main\.c .* 0 || 1: Success +^\[main\.assertion\.3\] file main\.c .* 1 && 1: Success +^\[main\.assertion\.4\] file main\.c .* 1 || x: Success +^\[main\.assertion\.5\] file main\.c .* y || 1: Success ^EXIT=0$ ^SIGNAL=0$ -- diff --git a/regression/goto-analyzer/constant_propagation_01/main.c b/regression/goto-analyzer/constant_propagation_01/main.c index 0185f49f3c1..49d90994aa2 100644 --- a/regression/goto-analyzer/constant_propagation_01/main.c +++ b/regression/goto-analyzer/constant_propagation_01/main.c @@ -8,7 +8,7 @@ int main() { int x=1,y=2,z; z=x+y; - assert(z==3); + __CPROVER_assert(z==3, "z==3"); } } diff --git a/regression/goto-analyzer/constant_propagation_01/test.desc b/regression/goto-analyzer/constant_propagation_01/test.desc index e10d3883cc4..755dba52ce4 100644 --- a/regression/goto-analyzer/constant_propagation_01/test.desc +++ b/regression/goto-analyzer/constant_propagation_01/test.desc @@ -3,7 +3,7 @@ main.c --variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 2, assigns: 5, function calls: 0$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 5, function calls: 0$ ^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 12, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_02/main.c b/regression/goto-analyzer/constant_propagation_02/main.c index db0c8dc3f3e..e6f6764badf 100644 --- a/regression/goto-analyzer/constant_propagation_02/main.c +++ b/regression/goto-analyzer/constant_propagation_02/main.c @@ -3,10 +3,10 @@ int main() { int i=0, j=2; - if (i==0) + if (i==0) { i++; j++; } - assert(j!=3); + __CPROVER_assert(j!=3, "j!=3"); } diff --git a/regression/goto-analyzer/constant_propagation_03/main.c b/regression/goto-analyzer/constant_propagation_03/main.c index 09a5434dead..3a929f776b8 100644 --- a/regression/goto-analyzer/constant_propagation_03/main.c +++ b/regression/goto-analyzer/constant_propagation_03/main.c @@ -3,10 +3,10 @@ int main() { int i=0, j=2; - if (i==0) + if (i==0) { i++; j++; } - assert(j==3); + __CPROVER_assert(j==3, "j==3"); } diff --git a/regression/goto-analyzer/constant_propagation_04/main.c b/regression/goto-analyzer/constant_propagation_04/main.c index 2c6c3f39db1..b667e66dfe5 100644 --- a/regression/goto-analyzer/constant_propagation_04/main.c +++ b/regression/goto-analyzer/constant_propagation_04/main.c @@ -3,10 +3,10 @@ int main() { int i=0, j=2; - if (i<50) + if (i<50) { i++; j++; } - assert(j==3); + __CPROVER_assert(j==3, "j==3"); } diff --git a/regression/goto-analyzer/constant_propagation_05/main.c b/regression/goto-analyzer/constant_propagation_05/main.c index b740fc135c0..7f5ae516853 100644 --- a/regression/goto-analyzer/constant_propagation_05/main.c +++ b/regression/goto-analyzer/constant_propagation_05/main.c @@ -3,10 +3,10 @@ int main() { int i=0, j=2; - if (i<50) + if (i<50) { i++; j++; } - assert(j!=3); + __CPROVER_assert(j!=3, "j!=3"); } diff --git a/regression/goto-analyzer/constant_propagation_05/test.desc b/regression/goto-analyzer/constant_propagation_05/test.desc index 7af5c6610d3..2ebfd52ca32 100644 --- a/regression/goto-analyzer/constant_propagation_05/test.desc +++ b/regression/goto-analyzer/constant_propagation_05/test.desc @@ -3,6 +3,6 @@ main.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] .* assertion j != 3: Failure \(if reachable\)$ +^\[main\.assertion\.1\] .* j!=3: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_06/main.c b/regression/goto-analyzer/constant_propagation_06/main.c index 6290aa89e6b..4595085a85e 100644 --- a/regression/goto-analyzer/constant_propagation_06/main.c +++ b/regression/goto-analyzer/constant_propagation_06/main.c @@ -3,11 +3,11 @@ int main() { int i=0, j=2; - while (i<50) + while (i<50) { i++; j++; } - assert(i<51); + __CPROVER_assert(i<51, "i<51"); } diff --git a/regression/goto-analyzer/constant_propagation_06/test.desc b/regression/goto-analyzer/constant_propagation_06/test.desc index f8b93dbf345..bf8b8c40eac 100644 --- a/regression/goto-analyzer/constant_propagation_06/test.desc +++ b/regression/goto-analyzer/constant_propagation_06/test.desc @@ -3,6 +3,6 @@ main.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line 11 function main, assertion i\s*<\s*51: Unknown$ +^\[main.assertion.1\] .* i\s*<\s*51: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_07/main.c b/regression/goto-analyzer/constant_propagation_07/main.c index 1fb6fee8e15..83db927383e 100644 --- a/regression/goto-analyzer/constant_propagation_07/main.c +++ b/regression/goto-analyzer/constant_propagation_07/main.c @@ -17,7 +17,7 @@ int main() j = j + 1; i = i + 1; } - assert(!(i < 2)); + __CPROVER_assert(!(i < 2), "!(i < 2)"); } } return 0; diff --git a/regression/goto-analyzer/constant_propagation_08/main.c b/regression/goto-analyzer/constant_propagation_08/main.c index 295e23c636d..fa70c7b001d 100644 --- a/regression/goto-analyzer/constant_propagation_08/main.c +++ b/regression/goto-analyzer/constant_propagation_08/main.c @@ -10,7 +10,7 @@ int main() else a[1]=2; - assert(a[0]==1 || a[1]==2); + __CPROVER_assert(a[0]==1 || a[1]==2, "a[0]==1 || a[1]==2"); return 0; } diff --git a/regression/goto-analyzer/constant_propagation_09/main.c b/regression/goto-analyzer/constant_propagation_09/main.c index 9bd38159f67..e3ad2204ca2 100644 --- a/regression/goto-analyzer/constant_propagation_09/main.c +++ b/regression/goto-analyzer/constant_propagation_09/main.c @@ -6,7 +6,7 @@ int main() if (a[0]==0) a[0]=1; - assert(a[0]==0); + __CPROVER_assert(a[0]==0, "a[0]==0"); return 0; } diff --git a/regression/goto-analyzer/constant_propagation_10/main.c b/regression/goto-analyzer/constant_propagation_10/main.c index 217faa4c9a7..be7b386afad 100644 --- a/regression/goto-analyzer/constant_propagation_10/main.c +++ b/regression/goto-analyzer/constant_propagation_10/main.c @@ -7,7 +7,7 @@ int main() if (a[0]==0) a[0]=1; - assert(a[0]==2); + __CPROVER_assert(a[0]==2, "a[0]==2"); return 0; } diff --git a/regression/goto-analyzer/constant_propagation_10/test.desc b/regression/goto-analyzer/constant_propagation_10/test.desc index 37206fe4887..43d07eb8172 100644 --- a/regression/goto-analyzer/constant_propagation_10/test.desc +++ b/regression/goto-analyzer/constant_propagation_10/test.desc @@ -3,6 +3,6 @@ main.c --variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] .* assertion a\[\(signed long int\)0\] == 2: Failure \(if reachable\)$ +^\[main\.assertion\.1\] .* a\[0\]==2: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_11/main.c b/regression/goto-analyzer/constant_propagation_11/main.c index cefa0c479ab..40e8b43d2e3 100644 --- a/regression/goto-analyzer/constant_propagation_11/main.c +++ b/regression/goto-analyzer/constant_propagation_11/main.c @@ -6,7 +6,7 @@ int main() if (a[0]==0) a[0]=1; - assert(a[0]==1 /*|| a[0]==2*/); + __CPROVER_assert(a[0]==1 /*|| a[0]==2*/, "a[0]==1 /*|| a[0]==2*/"); return 0; } diff --git a/regression/goto-analyzer/constant_propagation_12/main.c b/regression/goto-analyzer/constant_propagation_12/main.c index a8379b64712..e86aaba5d7b 100644 --- a/regression/goto-analyzer/constant_propagation_12/main.c +++ b/regression/goto-analyzer/constant_propagation_12/main.c @@ -6,7 +6,7 @@ int main() if (i==0) y=1; - assert(y==1); + __CPROVER_assert(y==1, "y==1"); return 0; } diff --git a/regression/goto-analyzer/constant_propagation_13/main.c b/regression/goto-analyzer/constant_propagation_13/main.c index a4307c4d431..393ebae92c9 100644 --- a/regression/goto-analyzer/constant_propagation_13/main.c +++ b/regression/goto-analyzer/constant_propagation_13/main.c @@ -6,7 +6,7 @@ int main() if (i==0) y=1; - assert(y==0); + __CPROVER_assert(y==0, "y==0"); return 0; } diff --git a/regression/goto-analyzer/constant_propagation_13/test.desc b/regression/goto-analyzer/constant_propagation_13/test.desc index 0b7f0cbfb1c..40ff1a7bf30 100644 --- a/regression/goto-analyzer/constant_propagation_13/test.desc +++ b/regression/goto-analyzer/constant_propagation_13/test.desc @@ -3,6 +3,6 @@ main.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] .* assertion y == 0: Failure \(if reachable\)$ +^\[main\.assertion\.1\] .* y==0: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_14/main.c b/regression/goto-analyzer/constant_propagation_14/main.c index 7a659b87c60..7b38dd7be9e 100644 --- a/regression/goto-analyzer/constant_propagation_14/main.c +++ b/regression/goto-analyzer/constant_propagation_14/main.c @@ -5,11 +5,11 @@ int main() if (a[0]==0) a[0]=1; - else + else a[0]=2; - assert(a[0]==1 || a[0]==2); - assert(a[0]==1 && a[0]==2); + __CPROVER_assert(a[0]==1 || a[0]==2, "a[0]==1 || a[0]==2"); + __CPROVER_assert(a[0]==1 && a[0]==2, "a[0]==1 && a[0]==2"); return 0; } diff --git a/regression/goto-analyzer/constant_propagation_14/test.desc b/regression/goto-analyzer/constant_propagation_14/test.desc index f9e545bc125..a0c6e4c6a2d 100644 --- a/regression/goto-analyzer/constant_propagation_14/test.desc +++ b/regression/goto-analyzer/constant_propagation_14/test.desc @@ -3,7 +3,7 @@ main.c --variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -\[main\.assertion\.1\] .* assertion tmp_if_expr\$1: Success$ -\[main\.assertion\.2\] .* assertion tmp_if_expr\$2: Failure \(if reachable\)$ +\[main\.assertion\.1\] .* a\[0\]==1 || a\[0\]==2: Success$ +\[main\.assertion\.2\] .* a\[0\]==1 && a\[0\]==2: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_15/main.c b/regression/goto-analyzer/constant_propagation_15/main.c index e3dd672831d..4e63b0f873a 100644 --- a/regression/goto-analyzer/constant_propagation_15/main.c +++ b/regression/goto-analyzer/constant_propagation_15/main.c @@ -6,7 +6,7 @@ int main() if (a[0]==0) a[0]=1; - assert(a[0]==2); + __CPROVER_assert(a[0]==2, "a[0]==2"); return 0; } diff --git a/regression/goto-analyzer/constant_propagation_15/test.desc b/regression/goto-analyzer/constant_propagation_15/test.desc index 37206fe4887..43d07eb8172 100644 --- a/regression/goto-analyzer/constant_propagation_15/test.desc +++ b/regression/goto-analyzer/constant_propagation_15/test.desc @@ -3,6 +3,6 @@ main.c --variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] .* assertion a\[\(signed long int\)0\] == 2: Failure \(if reachable\)$ +^\[main\.assertion\.1\] .* a\[0\]==2: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_17/main.c b/regression/goto-analyzer/constant_propagation_17/main.c index 40b04edfdd0..cb41fe9e87f 100644 --- a/regression/goto-analyzer/constant_propagation_17/main.c +++ b/regression/goto-analyzer/constant_propagation_17/main.c @@ -4,11 +4,11 @@ int main() { int i=0, j=2; - while (i<50) + while (i<50) { i++; j++; } - assert(i<51); + __CPROVER_assert(i<51, "i<51"); } diff --git a/regression/goto-analyzer/constant_propagation_17/test.desc b/regression/goto-analyzer/constant_propagation_17/test.desc index 76dc0fca897..4b7db991084 100644 --- a/regression/goto-analyzer/constant_propagation_17/test.desc +++ b/regression/goto-analyzer/constant_propagation_17/test.desc @@ -3,6 +3,6 @@ main.c --constants --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line 12 function main, assertion i\s*<\s*51: (Unknown|Failure \(if reachable\))$ +^\[main\.assertion\.1\] .* i\s*<\s*51: (Unknown|Failure \(if reachable\))$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/demo/main.c b/regression/goto-analyzer/demo/main.c index d96e402fdf3..cbea87ebae9 100644 --- a/regression/goto-analyzer/demo/main.c +++ b/regression/goto-analyzer/demo/main.c @@ -28,37 +28,37 @@ void func(int unknown) } // Knows we took if statement so can conclude assertion is true - assert(j==3); // Verified + __CPROVER_assert(j==3, "j==3"); // Verified int value=4; int * p2v = &value; int ** pp2v = &p2v; - assert(*p2v==4); - assert(**pp2v==4); + __CPROVER_assert(*p2v==4, "*p2v==4"); + __CPROVER_assert(**pp2v==4, "**pp2v==4"); value=10; // Tracks the value pointed to has changed - assert(*p2v==10); - assert(**pp2v==10); + __CPROVER_assert(*p2v==10, "*p2v==10"); + __CPROVER_assert(**pp2v==10, "**pp2v==10"); *p2v = 15; - assert(value==15); - assert(*p2v==15); - assert(**pp2v==15); + __CPROVER_assert(value==15, "value==15"); + __CPROVER_assert(*p2v==15, "*p2v==15"); + __CPROVER_assert(**pp2v==15, "**pp2v==15"); **pp2v = 20; - assert(value==20); - assert(*p2v==20); - assert(**pp2v==20); + __CPROVER_assert(value==20, "value==20"); + __CPROVER_assert(*p2v==20, "*p2v==20"); + __CPROVER_assert(**pp2v==20, "**pp2v==20"); int other = 5; p2v = &other; - assert(*p2v==5); - assert(**pp2v==5); + __CPROVER_assert(*p2v==5, "*p2v==5"); + __CPROVER_assert(**pp2v==5, "**pp2v==5"); if(unknown > 10) { @@ -69,9 +69,9 @@ void func(int unknown) p2v = &other; } - assert(pp2v==&p2v); // success (even though p2v has changed) - assert(*p2v==10); // unknown since we don't know anymore what p2v points to - assert(**pp2v==10); // unknown + __CPROVER_assert(pp2v==&p2v, "pp2v==&p2v"); // success (even though p2v has changed) + __CPROVER_assert(*p2v==10, "*p2v==10"); // unknown since we don't know anymore what p2v points to + __CPROVER_assert(**pp2v==10, "**pp2v==10"); // unknown // Running this through --simplify will yield: // yp = &x @@ -84,8 +84,8 @@ void func(int unknown) int array[4] = {0, 1 , 2, 3}; - assert(array[0] == 0); // Success - assert(array[3] == 3); // Success + __CPROVER_assert(array[0] == 0, "array[0] == 0"); // Success + __CPROVER_assert(array[3] == 3, "array[3] == 3"); // Success if(unknown > 10) { @@ -99,10 +99,10 @@ void func(int unknown) array[2] = 10; } - assert(array[0] == 4); // Success - assert(array[1] == 1); // Success - assert(array[2] == 5); // Unknown - assert(array[3] == 3); // Success + __CPROVER_assert(array[0] == 4, "array[0] == 4"); // Success + __CPROVER_assert(array[1] == 1, "array[1] == 1"); // Success + __CPROVER_assert(array[2] == 5, "array[2] == 5"); // Unknown + __CPROVER_assert(array[3] == 3, "array[3] == 3"); // Success typedef struct @@ -114,6 +114,6 @@ void func(int unknown) struct_t s; s.a = 1; - assert(s.a == 1); - assert(s.a == 2); + __CPROVER_assert(s.a == 1, "s.a == 1"); + __CPROVER_assert(s.a == 2, "s.a == 2"); } diff --git a/regression/goto-analyzer/intervals_01/main.c b/regression/goto-analyzer/intervals_01/main.c index aeb37b99e07..68f3c189bea 100644 --- a/regression/goto-analyzer/intervals_01/main.c +++ b/regression/goto-analyzer/intervals_01/main.c @@ -4,26 +4,26 @@ int main() int i, j=20; if(i>=20) - assert(i>=10); + __CPROVER_assert(i>=10, "i>=10"); if(i>=10 && i<=20) - assert(i!=30); + __CPROVER_assert(i!=30, "i!=30"); if(i>=10 && i<=20) - assert(i!=15); // fails + __CPROVER_assert(i!=15, "i!=15"); // fails if(i<1 && i>10) - assert(0); + __CPROVER_assert(0, "0"); if(i>=10 && j>=i) - assert(j>=10); + __CPROVER_assert(j>=10, "j>=10"); if(i>=j) - assert(i>=j); // fails + __CPROVER_assert(i>=j, "i>=j"); // fails if(i>10) - assert(i>=11); + __CPROVER_assert(i>=11, "i>=11"); if(i<=100 && j=\s*10: Success$ -^\[main.assertion.2\] file main.c line 10 function main, assertion i\s*!=\s*30: Success$ -^\[main.assertion.3\] file main.c line 13 function main, assertion i\s*!=\s*15: Unknown$ -^\[main.assertion.4\] file main.c line 16 function main, assertion 0: Success$ -^\[main.assertion.5\] file main.c line 19 function main, assertion j\s*>=\s*10: Success$ -^\[main.assertion.6\] file main.c line 22 function main, assertion i\s*>=\s*j: Unknown$ -^\[main.assertion.7\] file main.c line 25 function main, assertion i\s*>=\s*11: Success$ -^\[main.assertion.8]\ file main.c line 28 function main, assertion j\s*<\s*100: Success$ +^\[main\.assertion\.1\] .* i\s*>=\s*10: Success$ +^\[main\.assertion\.2\] .* i\s*!=\s*30: Success$ +^\[main\.assertion\.3\] .* i\s*!=\s*15: Unknown$ +^\[main\.assertion\.4\] .* 0: Success$ +^\[main\.assertion\.5\] .* j\s*>=\s*10: Success$ +^\[main\.assertion\.6\] .* i\s*>=\s*j: Unknown$ +^\[main\.assertion\.7\] .* i\s*>=\s*11: Success$ +^\[main\.assertion\.8]\ .* j\s*<\s*100: Success$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/intervals_02/main.c b/regression/goto-analyzer/intervals_02/main.c index 00659353325..eecb30f3613 100644 --- a/regression/goto-analyzer/intervals_02/main.c +++ b/regression/goto-analyzer/intervals_02/main.c @@ -2,7 +2,7 @@ int main(){ int x; if (x > 0 && x < 20) { - assert(x > -10 && x < 100); + __CPROVER_assert(x > -10 && x < 100, "x > -10 && x < 100"); } return 0; } diff --git a/regression/goto-analyzer/intervals_03/main.c b/regression/goto-analyzer/intervals_03/main.c index de8c1eead32..816d67172dc 100644 --- a/regression/goto-analyzer/intervals_03/main.c +++ b/regression/goto-analyzer/intervals_03/main.c @@ -3,7 +3,7 @@ int main(){ int x; if (x > 0) { if (x < 20) { - assert(x > -10 || x < 100); + __CPROVER_assert(x > -10 || x < 100, "x > -10 || x < 100"); } } return 0; diff --git a/regression/goto-analyzer/intervals_04/main.c b/regression/goto-analyzer/intervals_04/main.c index 1ca11e32143..6dc4da4fd02 100644 --- a/regression/goto-analyzer/intervals_04/main.c +++ b/regression/goto-analyzer/intervals_04/main.c @@ -5,7 +5,7 @@ int main() if(i>0) if(i<3) - assert(i>=1 && i<=2); + __CPROVER_assert(i>=1 && i<=2, "i>=1 && i<=2"); return 0; } diff --git a/regression/goto-analyzer/intervals_05/main.c b/regression/goto-analyzer/intervals_05/main.c index 2cd79130dc9..b1337e9f72c 100644 --- a/regression/goto-analyzer/intervals_05/main.c +++ b/regression/goto-analyzer/intervals_05/main.c @@ -5,7 +5,7 @@ int main() if(i>0) if(i<3) - assert(i>=1 || i<=2); + __CPROVER_assert(i>=1 || i<=2, "i>=1 || i<=2"); return 0; } diff --git a/regression/goto-analyzer/intervals_06/main.c b/regression/goto-analyzer/intervals_06/main.c index 0e8a1f37c13..aa55440a7eb 100644 --- a/regression/goto-analyzer/intervals_06/main.c +++ b/regression/goto-analyzer/intervals_06/main.c @@ -3,7 +3,7 @@ int main(){ int x; if (x > 0) { if (x < 20) { - assert(x < -10 || x > 100); + __CPROVER_assert(x < -10 || x > 100, "x < -10 || x > 100"); } } return 0; diff --git a/regression/goto-analyzer/intervals_07/main.c b/regression/goto-analyzer/intervals_07/main.c index 75da9413b97..d4c5a079e53 100644 --- a/regression/goto-analyzer/intervals_07/main.c +++ b/regression/goto-analyzer/intervals_07/main.c @@ -3,7 +3,7 @@ int main(){ int x; if (x > 0) { if (x < 20) { - assert(x < -10 && x > 100); + __CPROVER_assert(x < -10 && x > 100, "x < -10 && x > 100"); } } return 0; diff --git a/regression/goto-analyzer/intervals_08/main.c b/regression/goto-analyzer/intervals_08/main.c index 3bcb7fe69c7..8c4b6683739 100644 --- a/regression/goto-analyzer/intervals_08/main.c +++ b/regression/goto-analyzer/intervals_08/main.c @@ -2,7 +2,7 @@ int main(){ int x; if (x > 0 && x < 20) { - assert(x < -10 && x < 100); + __CPROVER_assert(x < -10 && x < 100, "x < -10 && x < 100"); } return 0; } diff --git a/regression/goto-analyzer/intervals_09/main.c b/regression/goto-analyzer/intervals_09/main.c index 73b8e73dc85..6dc4da4fd02 100644 --- a/regression/goto-analyzer/intervals_09/main.c +++ b/regression/goto-analyzer/intervals_09/main.c @@ -2,10 +2,10 @@ int main() { int i; - + if(i>0) if(i<3) - assert(i>=1 && i<=2); - + __CPROVER_assert(i>=1 && i<=2, "i>=1 && i<=2"); + return 0; -} +} diff --git a/regression/goto-analyzer/intervals_10/main.c b/regression/goto-analyzer/intervals_10/main.c index b245b3f5b7c..8eb55131936 100644 --- a/regression/goto-analyzer/intervals_10/main.c +++ b/regression/goto-analyzer/intervals_10/main.c @@ -4,17 +4,17 @@ int main() int i, j; if(i<=100 && j100); // fails + __CPROVER_assert(j>100, "j>100"); // fails if(i<=100 && j=-1 && x[i]<=1); x_aux[i]=0; y_aux[i]=0; @@ -27,12 +27,12 @@ int main() { /* Num, x values */ for (j = 0; j < Blen; j++) { y[i] = y[i] + B[j]*x_aux[j]; - assert(y[i]>=-1.0f && y[i]<=1.0f); //success + __CPROVER_assert(y[i]>=-1.0f && y[i]<=1.0f, "y[i]>=-1.0f && y[i]<=1.0f"); //success } /* Den, y values */ for(j=0;j=-1.0f && y[i]<=1.0f); //fails + __CPROVER_assert(y[i]>=-1.0f && y[i]<=1.0f, "y[i]>=-1.0f && y[i]<=1.0f"); //fails } /* Update past y values */ for(j=Alen-2;j>=1;j--) diff --git a/regression/goto-analyzer/intervals_12/main.c b/regression/goto-analyzer/intervals_12/main.c index 506e118f898..c5ff1c34061 100644 --- a/regression/goto-analyzer/intervals_12/main.c +++ b/regression/goto-analyzer/intervals_12/main.c @@ -4,10 +4,10 @@ int main (void) { int j; if (i <= 0 && j < i) - assert(j < 0); + __CPROVER_assert(j < 0, "j < 0"); if (j < i && i <= 0) - assert(j < 0); + __CPROVER_assert(j < 0, "j < 0"); return 0; } diff --git a/regression/goto-analyzer/intervals_13/main.c b/regression/goto-analyzer/intervals_13/main.c index b631969e8f6..0de4b75dc1d 100644 --- a/regression/goto-analyzer/intervals_13/main.c +++ b/regression/goto-analyzer/intervals_13/main.c @@ -4,26 +4,26 @@ int main() int i, j=20; if(i>=20) - assert(i>=10); // success + __CPROVER_assert(i>=10, "i>=10"); // success if(i>=10 && i<=20) - assert(i!=30); // success + __CPROVER_assert(i!=30, "i!=30"); // success if(i>=10 && i<=20) - assert(i!=15); // fails + __CPROVER_assert(i!=15, "i!=15"); // fails if(i<1 && i>10) - assert(0); // success + __CPROVER_assert(0, "0"); // success if(i>=10 && j>=i) - assert(j>=10); // success + __CPROVER_assert(j>=10, "j>=10"); // success if(i>=j) - assert(i>=j); // unknown + __CPROVER_assert(i>=j, "i>=j"); // unknown if(i>10) - assert(i>=11); // success + __CPROVER_assert(i>=11, "i>=11"); // success if(i<=100 && j=\s*10: Success$ -^\[main.assertion.2\] file main.c line 10 function main, assertion i\s*!=\s*30: Success$ -^\[main.assertion.3\] file main.c line 13 function main, assertion i\s*!=\s*15: Unknown$ -^\[main.assertion.4\] file main.c line 16 function main, assertion 0: Success$ -^\[main.assertion.5\] file main.c line 19 function main, assertion j\s*>=\s*10: Success$ -^\[main.assertion.6\] file main.c line 22 function main, assertion i\s*>=\s*j: Unknown$ -^\[main.assertion.7\] file main.c line 25 function main, assertion i\s*>=\s*11: Success$ -^\[main.assertion.8\] file main.c line 28 function main, assertion j\s*<\s*100: Success$ +^\[main\.assertion\.1\] .* i\s*>=\s*10: Success$ +^\[main\.assertion\.2\] .* i\s*!=\s*30: Success$ +^\[main\.assertion\.3\] .* i\s*!=\s*15: Unknown$ +^\[main\.assertion\.4\] .* 0: Success$ +^\[main\.assertion\.5\] .* j\s*>=\s*10: Success$ +^\[main\.assertion\.6\] .* i\s*>=\s*j: Unknown$ +^\[main\.assertion\.7\] .* i\s*>=\s*11: Success$ +^\[main\.assertion\.8\] .* j\s*<\s*100: Success$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/intervals_14/main.c b/regression/goto-analyzer/intervals_14/main.c index 7e4d53d5e06..106d3fb61e1 100644 --- a/regression/goto-analyzer/intervals_14/main.c +++ b/regression/goto-analyzer/intervals_14/main.c @@ -3,13 +3,13 @@ int main() { int i=0, j=2; - while (i<=50) + while (i<=50) { i++; j++; } - assert(i<50); - assert(i<51); - assert(i<52); + __CPROVER_assert(i<50, "i<50"); + __CPROVER_assert(i<51, "i<51"); + __CPROVER_assert(i<52, "i<52"); } diff --git a/regression/goto-analyzer/intervals_15/main.c b/regression/goto-analyzer/intervals_15/main.c index 52ef248b772..40673b0e5e6 100644 --- a/regression/goto-analyzer/intervals_15/main.c +++ b/regression/goto-analyzer/intervals_15/main.c @@ -3,11 +3,11 @@ int main() { int i=0, j=2; - while (i<=50) + while (i<=50) { i++; j++; } - assert(j<52); + __CPROVER_assert(j<52, "j<52"); } diff --git a/regression/goto-analyzer/intervals_15/test.desc b/regression/goto-analyzer/intervals_15/test.desc index e61667afcd4..91036e37a4c 100644 --- a/regression/goto-analyzer/intervals_15/test.desc +++ b/regression/goto-analyzer/intervals_15/test.desc @@ -3,6 +3,6 @@ main.c --intervals --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line 11 function main, assertion j\s*<\s*52: Unknown$ +^\[main\.assertion\.1\] .* j\s*<\s*52: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/intervals_16/main.c b/regression/goto-analyzer/intervals_16/main.c index 52ef248b772..40673b0e5e6 100644 --- a/regression/goto-analyzer/intervals_16/main.c +++ b/regression/goto-analyzer/intervals_16/main.c @@ -3,11 +3,11 @@ int main() { int i=0, j=2; - while (i<=50) + while (i<=50) { i++; j++; } - assert(j<52); + __CPROVER_assert(j<52, "j<52"); } diff --git a/regression/goto-analyzer/intervals_16/test.desc b/regression/goto-analyzer/intervals_16/test.desc index c23e2bcf4f5..ef9d6ae0a0a 100644 --- a/regression/goto-analyzer/intervals_16/test.desc +++ b/regression/goto-analyzer/intervals_16/test.desc @@ -3,6 +3,6 @@ main.c --intervals --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line 11 function main, assertion j\s*<\s*52: (Unknown|Failure \(if reachable\))$ +^\[main\.assertion\.1\] .* j\s*<\s*52: (Unknown|Failure \(if reachable\))$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/minimal-reproducer-for-struct-problem/minimal_reproducer_for_struct_problem.c b/regression/goto-analyzer/minimal-reproducer-for-struct-problem/minimal_reproducer_for_struct_problem.c index a484f619fe5..b763f672118 100644 --- a/regression/goto-analyzer/minimal-reproducer-for-struct-problem/minimal_reproducer_for_struct_problem.c +++ b/regression/goto-analyzer/minimal-reproducer-for-struct-problem/minimal_reproducer_for_struct_problem.c @@ -10,19 +10,19 @@ int main(int argc, char *argv[]) struct int_struct x = {0}; x.a = 0; - assert(x.a==0); - assert(x.a==1); + __CPROVER_assert(x.a==0, "x.a==0"); + __CPROVER_assert(x.a==1, "x.a==1"); if(argc>2) { - assert(x.a==0); - assert(x.a==1); + __CPROVER_assert(x.a==0, "x.a==0"); + __CPROVER_assert(x.a==1, "x.a==1"); x.a=1; - assert(x.a==0); - assert(x.a==1); + __CPROVER_assert(x.a==0, "x.a==0"); + __CPROVER_assert(x.a==1, "x.a==1"); } - assert(x.a==0); - assert(x.a==1); + __CPROVER_assert(x.a==0, "x.a==0"); + __CPROVER_assert(x.a==1, "x.a==1"); return 0; } diff --git a/regression/goto-analyzer/minimal-reproducer-for-struct-problem/test.desc b/regression/goto-analyzer/minimal-reproducer-for-struct-problem/test.desc index e68739d9b9b..48983ce22d7 100644 --- a/regression/goto-analyzer/minimal-reproducer-for-struct-problem/test.desc +++ b/regression/goto-analyzer/minimal-reproducer-for-struct-problem/test.desc @@ -3,13 +3,13 @@ minimal_reproducer_for_struct_problem.c --variable --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x.a==0: Success$ -^\[main.assertion.2\] .* assertion x.a==1: Failure \(if reachable\)$ -^\[main.assertion.3\] .* assertion x.a==0: Success$ -^\[main.assertion.4\] .* assertion x.a==1: Failure \(if reachable\)$ -^\[main.assertion.5\] .* assertion x.a==0: Failure \(if reachable\)$ -^\[main.assertion.6\] .* assertion x.a==1: Success$ -^\[main.assertion.7\] .* assertion x.a==0: Unknown$ -^\[main.assertion.8\] .* assertion x.a==1: Unknown$ +^\[main.assertion.1\] .* x.a==0: Success$ +^\[main.assertion.2\] .* x.a==1: Failure \(if reachable\)$ +^\[main.assertion.3\] .* x.a==0: Success$ +^\[main.assertion.4\] .* x.a==1: Failure \(if reachable\)$ +^\[main.assertion.5\] .* x.a==0: Failure \(if reachable\)$ +^\[main.assertion.6\] .* x.a==1: Success$ +^\[main.assertion.7\] .* x.a==0: Unknown$ +^\[main.assertion.8\] .* x.a==1: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-common-files/array_of_array_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/array_of_array_sensitivity_tests.c index 63af187ade2..0ea6f6ac258 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/array_of_array_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/array_of_array_sensitivity_tests.c @@ -8,34 +8,34 @@ int main(int argc, char *argv[]) int b[3][3]={{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}; // Test if we can represent uniform constant arrays - assert(a[1][2]==0); - assert(a[1][2]==1); + __CPROVER_assert(a[1][2]==0, "a[1][2]==0"); + __CPROVER_assert(a[1][2]==1, "a[1][2]==1"); // Test if we can represent constant arrays which aren't uniform - assert(b[1][2]==5); - assert(b[1][2]==0); + __CPROVER_assert(b[1][2]==5, "b[1][2]==5"); + __CPROVER_assert(b[1][2]==0, "b[1][2]==0"); // Test alternative syntax for accessing an array value - assert(*(b[1]+2)==5); - assert(*(b[1]+2)==0); - assert((*(b+1))[2]==5); - assert((*(b+1))[2]==0); - assert(*(*(b+1)+2)==5); - assert(*(*(b+1)+2)==0); - assert(1[b][2]==5); - assert(1[b][2]==0); - assert(*(1[b]+2)==5); - assert(*(1[b]+2)==0); - assert((*(1+b))[2]==5); - assert((*(1+b))[2]==0); - assert(*(*(1+b)+2)==5); - assert(*(*(1+b)+2)==0); - assert(2[1[b]]==5); - assert(2[1[b]]==0); - assert(*(2+1[b])==5); - assert(*(2+1[b])==0); - assert(*(2+*(1+b))==5); - assert(*(2+*(1+b))==0); + __CPROVER_assert(*(b[1]+2)==5, "*(b[1]+2)==5"); + __CPROVER_assert(*(b[1]+2)==0, "*(b[1]+2)==0"); + __CPROVER_assert((*(b+1))[2]==5, "(*(b+1))[2]==5"); + __CPROVER_assert((*(b+1))[2]==0, "(*(b+1))[2]==0"); + __CPROVER_assert(*(*(b+1)+2)==5, "*(*(b+1)+2)==5"); + __CPROVER_assert(*(*(b+1)+2)==0, "*(*(b+1)+2)==0"); + __CPROVER_assert(1[b][2]==5, "1[b][2]==5"); + __CPROVER_assert(1[b][2]==0, "1[b][2]==0"); + __CPROVER_assert(*(1[b]+2)==5, "*(1[b]+2)==5"); + __CPROVER_assert(*(1[b]+2)==0, "*(1[b]+2)==0"); + __CPROVER_assert((*(1+b))[2]==5, "(*(1+b))[2]==5"); + __CPROVER_assert((*(1+b))[2]==0, "(*(1+b))[2]==0"); + __CPROVER_assert(*(*(1+b)+2)==5, "*(*(1+b)+2)==5"); + __CPROVER_assert(*(*(1+b)+2)==0, "*(*(1+b)+2)==0"); + __CPROVER_assert(2[1[b]]==5, "2[1[b]]==5"); + __CPROVER_assert(2[1[b]]==0, "2[1[b]]==0"); + __CPROVER_assert(*(2+1[b])==5, "*(2+1[b])==5"); + __CPROVER_assert(*(2+1[b])==0, "*(2+1[b])==0"); + __CPROVER_assert(*(2+*(1+b))==5, "*(2+*(1+b))==5"); + __CPROVER_assert(*(2+*(1+b))==0, "*(2+*(1+b))==0"); // Test how well we can deal with merging for an array value when there is one // possible value @@ -43,9 +43,9 @@ int main(int argc, char *argv[]) { a[0][1]=0; } - assert(a[0][1]==0); - assert(a[0][1]==1); - assert(a[0][2]==0); + __CPROVER_assert(a[0][1]==0, "a[0][1]==0"); + __CPROVER_assert(a[0][1]==1, "a[0][1]==1"); + __CPROVER_assert(a[0][2]==0, "a[0][2]==0"); // Test how well we can deal with merging for an array value when there are // two possible values @@ -53,9 +53,9 @@ int main(int argc, char *argv[]) { b[0][1]=2; } - assert(b[0][1]==2); - assert(b[0][1]==3); - assert(b[0][2]==2); + __CPROVER_assert(b[0][1]==2, "b[0][1]==2"); + __CPROVER_assert(b[0][1]==3, "b[0][1]==3"); + __CPROVER_assert(b[0][2]==2, "b[0][2]==2"); // Reset this change to ensure tests later work as expected b[0][1]=1; @@ -77,74 +77,74 @@ int main(int argc, char *argv[]) // Test how well we can deal with merging for an index on a uniform array when // the index has one possible value - assert(a[i][1]==0); - assert(a[i][1]==1); - assert(a[1][i]==0); - assert(a[1][i]==1); - assert(a[i][i]==0); - assert(a[i][i]==1); + __CPROVER_assert(a[i][1]==0, "a[i][1]==0"); + __CPROVER_assert(a[i][1]==1, "a[i][1]==1"); + __CPROVER_assert(a[1][i]==0, "a[1][i]==0"); + __CPROVER_assert(a[1][i]==1, "a[1][i]==1"); + __CPROVER_assert(a[i][i]==0, "a[i][i]==0"); + __CPROVER_assert(a[i][i]==1, "a[i][i]==1"); // Test how well we can deal with merging for an index on a uniform array when // the index has two possible values - assert(a[j][1]==0); - assert(a[j][1]==1); - assert(a[1][j]==0); - assert(a[1][j]==1); - assert(a[j][j]==0); - assert(a[j][j]==1); + __CPROVER_assert(a[j][1]==0, "a[j][1]==0"); + __CPROVER_assert(a[j][1]==1, "a[j][1]==1"); + __CPROVER_assert(a[1][j]==0, "a[1][j]==0"); + __CPROVER_assert(a[1][j]==1, "a[1][j]==1"); + __CPROVER_assert(a[j][j]==0, "a[j][j]==0"); + __CPROVER_assert(a[j][j]==1, "a[j][j]==1"); // Test how well we can deal with merging for an index on a non-uniform array - assert(b[i][1]==1); - assert(b[i][1]==11); - assert(b[1][i]==3); - assert(b[1][i]==11); - assert(b[i][i]==0); - assert(b[i][i]==11); + __CPROVER_assert(b[i][1]==1, "b[i][1]==1"); + __CPROVER_assert(b[i][1]==11, "b[i][1]==11"); + __CPROVER_assert(b[1][i]==3, "b[1][i]==3"); + __CPROVER_assert(b[1][i]==11, "b[1][i]==11"); + __CPROVER_assert(b[i][i]==0, "b[i][i]==0"); + __CPROVER_assert(b[i][i]==11, "b[i][i]==11"); // Test how well we can deal with merging for an index on a non-uniform array - assert(b[j][1]==1); - assert(b[j][1]==11); - assert(b[1][j]==3); - assert(b[1][j]==11); - assert(b[j][j]==0); - assert(b[j][j]==11); + __CPROVER_assert(b[j][1]==1, "b[j][1]==1"); + __CPROVER_assert(b[j][1]==11, "b[j][1]==11"); + __CPROVER_assert(b[1][j]==3, "b[1][j]==3"); + __CPROVER_assert(b[1][j]==11, "b[1][j]==11"); + __CPROVER_assert(b[j][j]==0, "b[j][j]==0"); + __CPROVER_assert(b[j][j]==11, "b[j][j]==11"); // Test how we deal with reading off the end of an array - assert(a[100][0]==0); - assert(a[0][100]==0); + __CPROVER_assert(a[100][0]==0, "a[100][0]==0"); + __CPROVER_assert(a[0][100]==0, "a[0][100]==0"); // Test how we deal with writing off the end of an array int c=0; a[100][0]=1; - assert(c==0); + __CPROVER_assert(c==0, "c==0"); c=0; a[0][100]=1; - assert(c==0); + __CPROVER_assert(c==0, "c==0"); // Test how we deal with merging for an index with one possible value when // writing to an array int ei[3][3]={{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; ei[i][1]=1; - assert(ei[0][1]==1); - assert(ei[0][1]==0); - assert(ei[2][1]==0); - assert(ei[2][1]==1); + __CPROVER_assert(ei[0][1]==1, "ei[0][1]==1"); + __CPROVER_assert(ei[0][1]==0, "ei[0][1]==0"); + __CPROVER_assert(ei[2][1]==0, "ei[2][1]==0"); + __CPROVER_assert(ei[2][1]==1, "ei[2][1]==1"); // Test how we deal with merging for an index with two possible values when // writing to an array int ej[3][3]={{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; ej[j][1]=1; - assert(ej[0][1]==0); - assert(ej[2][1]==0); + __CPROVER_assert(ej[0][1]==0, "ej[0][1]==0"); + __CPROVER_assert(ej[2][1]==0, "ej[2][1]==0"); // Test how we deal with merging for an index with two possible values when // it means writing to an array element that may be out of bounds int ek[3][3]={{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; c=0; ek[k][1]=1; - assert(ek[0][1]==0); - assert(c==0); + __CPROVER_assert(ek[0][1]==0, "ek[0][1]==0"); + __CPROVER_assert(c==0, "c==0"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c index b557202c3e5..f90bc5e2f0b 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c @@ -25,30 +25,30 @@ int main(int argc, char *argv[]) int *b[3]={&b0, &b1, &b2}; // Test if we can represent uniform constant arrays - assert(a[1]==&a0); - assert(a[1]==&a3); - assert(*a[1]==0); - assert(*a[1]==3); + __CPROVER_assert(a[1]==&a0, "a[1]==&a0"); + __CPROVER_assert(a[1]==&a3, "a[1]==&a3"); + __CPROVER_assert(*a[1]==0, "*a[1]==0"); + __CPROVER_assert(*a[1]==3, "*a[1]==3"); // Test if we can represent constant arrays which aren't uniform - assert(b[1]==&b1); - assert(b[1]==&b3); - assert(*b[1]==11); - assert(*b[1]==13); + __CPROVER_assert(b[1]==&b1, "b[1]==&b1"); + __CPROVER_assert(b[1]==&b3, "b[1]==&b3"); + __CPROVER_assert(*b[1]==11, "*b[1]==11"); + __CPROVER_assert(*b[1]==13, "*b[1]==13"); // Test alternative syntax for accessing an array value - assert(*(b+1)==&b1); - assert(*(b+1)==&b3); - assert(*(1+b)==&b1); - assert(*(1+b)==&b3); - assert(1[b]==&b1); - assert(1[b]==&b3); - assert(**(b+1)==11); - assert(**(b+1)==13); - assert(**(1+b)==11); - assert(**(1+b)==13); - assert(*1[b]==11); - assert(*1[b]==13); + __CPROVER_assert(*(b+1)==&b1, "*(b+1)==&b1"); + __CPROVER_assert(*(b+1)==&b3, "*(b+1)==&b3"); + __CPROVER_assert(*(1+b)==&b1, "*(1+b)==&b1"); + __CPROVER_assert(*(1+b)==&b3, "*(1+b)==&b3"); + __CPROVER_assert(1[b]==&b1, "1[b]==&b1"); + __CPROVER_assert(1[b]==&b3, "1[b]==&b3"); + __CPROVER_assert(**(b+1)==11, "**(b+1)==11"); + __CPROVER_assert(**(b+1)==13, "**(b+1)==13"); + __CPROVER_assert(**(1+b)==11, "**(1+b)==11"); + __CPROVER_assert(**(1+b)==13, "**(1+b)==13"); + __CPROVER_assert(*1[b]==11, "*1[b]==11"); + __CPROVER_assert(*1[b]==13, "*1[b]==13"); // c and d are arrays whose values requiring merging paths in the CFG. For // c[0] there is only one possibility after merging and for d[0] there are @@ -62,14 +62,14 @@ int main(int argc, char *argv[]) } // Test how well we can deal with merging for an array value - assert(c[0]==&c0); - assert(c[0]==&c3); - assert(d[0]==&d0); - assert(d[0]==&d3); - assert(*c[0]==20); - assert(*c[0]==23); - assert(*d[0]==30); - assert(*d[0]==33); + __CPROVER_assert(c[0]==&c0, "c[0]==&c0"); + __CPROVER_assert(c[0]==&c3, "c[0]==&c3"); + __CPROVER_assert(d[0]==&d0, "d[0]==&d0"); + __CPROVER_assert(d[0]==&d3, "d[0]==&d3"); + __CPROVER_assert(*c[0]==20, "*c[0]==20"); + __CPROVER_assert(*c[0]==23, "*c[0]==23"); + __CPROVER_assert(*d[0]==30, "*d[0]==30"); + __CPROVER_assert(*d[0]==33, "*d[0]==33"); // The variables i, j and k will be used as indexes into arrays of size 3. // They all require merging paths in the CFG. For i there is only one value on @@ -87,33 +87,33 @@ int main(int argc, char *argv[]) } // Test how well we can deal with merging for an index on a uniform array - assert(a[i]==&a0); - assert(a[i]==&a3); - assert(a[j]==&a0); - assert(a[j]==&a3); - assert(*a[i]==0); - assert(*a[i]==3); - assert(*a[j]==0); - assert(*a[j]==3); + __CPROVER_assert(a[i]==&a0, "a[i]==&a0"); + __CPROVER_assert(a[i]==&a3, "a[i]==&a3"); + __CPROVER_assert(a[j]==&a0, "a[j]==&a0"); + __CPROVER_assert(a[j]==&a3, "a[j]==&a3"); + __CPROVER_assert(*a[i]==0, "*a[i]==0"); + __CPROVER_assert(*a[i]==3, "*a[i]==3"); + __CPROVER_assert(*a[j]==0, "*a[j]==0"); + __CPROVER_assert(*a[j]==3, "*a[j]==3"); // Test how well we can deal with merging for an index on a non-uniform array - assert(b[i]==&b0); - assert(b[i]==&b1); - assert(b[j]==&b0); - assert(b[j]==&b3); - assert(*b[i]==10); - assert(*b[i]==11); - assert(*b[j]==10); - assert(*b[j]==13); + __CPROVER_assert(b[i]==&b0, "b[i]==&b0"); + __CPROVER_assert(b[i]==&b1, "b[i]==&b1"); + __CPROVER_assert(b[j]==&b0, "b[j]==&b0"); + __CPROVER_assert(b[j]==&b3, "b[j]==&b3"); + __CPROVER_assert(*b[i]==10, "*b[i]==10"); + __CPROVER_assert(*b[i]==11, "*b[i]==11"); + __CPROVER_assert(*b[j]==10, "*b[j]==10"); + __CPROVER_assert(*b[j]==13, "*b[j]==13"); // Test how we deal with reading off the end of an array - assert(a[100]==&a2); - assert(*a[100]==2); + __CPROVER_assert(a[100]==&a2, "a[100]==&a2"); + __CPROVER_assert(*a[100]==2, "*a[100]==2"); // Test how we deal with writing off the end of an array a[100]=&a2; - assert(b[1]==&b1); - assert(*b[1]==11); + __CPROVER_assert(b[1]==&b1, "b[1]==&b1"); + __CPROVER_assert(*b[1]==11, "*b[1]==11"); // Test how we deal with merging for an index with one possible value when // writing to an array @@ -121,14 +121,14 @@ int main(int argc, char *argv[]) int ei1=41; int *ei[3]={&ei0, &ei0, &ei0}; ei[i]=&ei1; - assert(ei[0]==&ei1); - assert(ei[0]==&ei0); - assert(ei[2]==&ei0); - assert(ei[2]==&ei1); - assert(*ei[0]==41); - assert(*ei[0]==40); - assert(*ei[2]==40); - assert(*ei[2]==41); + __CPROVER_assert(ei[0]==&ei1, "ei[0]==&ei1"); + __CPROVER_assert(ei[0]==&ei0, "ei[0]==&ei0"); + __CPROVER_assert(ei[2]==&ei0, "ei[2]==&ei0"); + __CPROVER_assert(ei[2]==&ei1, "ei[2]==&ei1"); + __CPROVER_assert(*ei[0]==41, "*ei[0]==41"); + __CPROVER_assert(*ei[0]==40, "*ei[0]==40"); + __CPROVER_assert(*ei[2]==40, "*ei[2]==40"); + __CPROVER_assert(*ei[2]==41, "*ei[2]==41"); // Test how we deal with merging for an index with two possible values when // writing to an array @@ -136,12 +136,12 @@ int main(int argc, char *argv[]) int ej1=51; int *ej[3]={&ej0, &ej0, &ej0}; ej[j]=&ej1; - assert(ej[0]==&ej0); - assert(ej[2]==&ej0); - assert(ej[2]==&ej1); - assert(*ej[0]==50); - assert(*ej[2]==50); - assert(*ej[2]==51); + __CPROVER_assert(ej[0]==&ej0, "ej[0]==&ej0"); + __CPROVER_assert(ej[2]==&ej0, "ej[2]==&ej0"); + __CPROVER_assert(ej[2]==&ej1, "ej[2]==&ej1"); + __CPROVER_assert(*ej[0]==50, "*ej[0]==50"); + __CPROVER_assert(*ej[2]==50, "*ej[2]==50"); + __CPROVER_assert(*ej[2]==51, "*ej[2]==51"); // Test how we deal with merging for an index with two possible values when // it means writing to an array element that may be out of bounds @@ -149,8 +149,8 @@ int main(int argc, char *argv[]) int ek1=61; int *ek[3]={&ek0, &ek0, &ek0}; ek[k]=&ek1; - assert(ek[0]==&ek0); - assert(*ek[0]==60); + __CPROVER_assert(ek[0]==&ek0, "ek[0]==&ek0"); + __CPROVER_assert(*ek[0]==60, "*ek[0]==60"); // Test writing to an unknown index (i.e. a merging write of the pointer) int x = 4; @@ -167,10 +167,10 @@ int main(int argc, char *argv[]) } *(ps[i])=4; - assert(*ps[0]==4); - assert(*ps[1]==4); - assert(x==4); - assert(y==4); + __CPROVER_assert(*ps[0]==4, "*ps[0]==4"); + __CPROVER_assert(*ps[1]==4, "*ps[1]==4"); + __CPROVER_assert(x==4, "x==4"); + __CPROVER_assert(y==4, "y==4"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-common-files/array_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/array_sensitivity_tests.c index 68bace194c8..b0b413b7014 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/array_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/array_sensitivity_tests.c @@ -8,20 +8,20 @@ int main(int argc, char *argv[]) int b[3]={1, 0, 0}; // Test if we can represent uniform constant arrays - assert(a[1]==0); - assert(a[1]==1); + __CPROVER_assert(a[1]==0, "a[1]==0"); + __CPROVER_assert(a[1]==1, "a[1]==1"); // Test if we can represent constant arrays which aren't uniform - assert(b[1]==0); - assert(b[1]==1); + __CPROVER_assert(b[1]==0, "b[1]==0"); + __CPROVER_assert(b[1]==1, "b[1]==1"); // Test alternative syntax for accessing an array value - assert(*(b+1)==0); - assert(*(b+1)==1); - assert(*(1+b)==0); - assert(*(1+b)==1); - assert(1[b]==0); - assert(1[b]==1); + __CPROVER_assert(*(b+1)==0, "*(b+1)==0"); + __CPROVER_assert(*(b+1)==1, "*(b+1)==1"); + __CPROVER_assert(*(1+b)==0, "*(1+b)==0"); + __CPROVER_assert(*(1+b)==1, "*(1+b)==1"); + __CPROVER_assert(1[b]==0, "1[b]==0"); + __CPROVER_assert(1[b]==1, "1[b]==1"); // c and d are arrays whose values requiring merging paths in the CFG. For // c[0] there is only one possibility after merging and for d[0] there are @@ -35,11 +35,11 @@ int main(int argc, char *argv[]) } // Test how well we can deal with merging for an array value - assert(c[0]==0); - assert(c[0]==1); - assert(d[0]==0); - assert(d[0]==2); - assert(d[1]==0); + __CPROVER_assert(c[0]==0, "c[0]==0"); + __CPROVER_assert(c[0]==1, "c[0]==1"); + __CPROVER_assert(d[0]==0, "d[0]==0"); + __CPROVER_assert(d[0]==2, "d[0]==2"); + __CPROVER_assert(d[1]==0, "d[1]==0"); // The variables i, j and k will be used as indexes into arrays of size 3. // They all require merging paths in the CFG. For i there is only one value on @@ -57,45 +57,45 @@ int main(int argc, char *argv[]) } // Test how well we can deal with merging for an index on a uniform array - assert(a[i]==0); - assert(a[i]==1); - assert(a[j]==0); - assert(a[j]==1); + __CPROVER_assert(a[i]==0, "a[i]==0"); + __CPROVER_assert(a[i]==1, "a[i]==1"); + __CPROVER_assert(a[j]==0, "a[j]==0"); + __CPROVER_assert(a[j]==1, "a[j]==1"); // Test how well we can deal with merging for an index on a non-uniform array - assert(b[i]==1); - assert(b[i]==0); - assert(b[j]==0); - assert(b[j]==1); + __CPROVER_assert(b[i]==1, "b[i]==1"); + __CPROVER_assert(b[i]==0, "b[i]==0"); + __CPROVER_assert(b[j]==0, "b[j]==0"); + __CPROVER_assert(b[j]==1, "b[j]==1"); // Test how we deal with reading off the end of an array - assert(a[100]==0); + __CPROVER_assert(a[100]==0, "a[100]==0"); // Test how we deal with writing off the end of an array a[100]=1; - assert(b[1]==0); + __CPROVER_assert(b[1]==0, "b[1]==0"); // Test how we deal with merging for an index with one possible value when // writing to an array int ei[3]={0, 0, 0}; ei[i]=1; - assert(ei[0]==1); - assert(ei[0]==0); - assert(ei[2]==0); - assert(ei[2]==1); + __CPROVER_assert(ei[0]==1, "ei[0]==1"); + __CPROVER_assert(ei[0]==0, "ei[0]==0"); + __CPROVER_assert(ei[2]==0, "ei[2]==0"); + __CPROVER_assert(ei[2]==1, "ei[2]==1"); // Test how we deal with merging for an index with two possible values when // writing to an array int ej[3]={0, 0, 0}; ej[j]=1; - assert(ej[0]==0); - assert(ej[2]==0); + __CPROVER_assert(ej[0]==0, "ej[0]==0"); + __CPROVER_assert(ej[2]==0, "ej[2]==0"); // Test how we deal with merging for an index with two possible values when // it means writing to an array element that may be out of bounds int ek[3]={0, 0, 0}; ek[k]=1; - assert(ek[0]==0); + __CPROVER_assert(ek[0]==0, "ek[0]==0"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-common-files/char_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/char_sensitivity_tests.c index 9e87454b68e..c56bc05e551 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/char_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/char_sensitivity_tests.c @@ -4,7 +4,7 @@ int main(int argc, char *argv[]) { // Test if we can represent constant chars char x='a'; - assert(x=='a'); - assert(x=='b'); + __CPROVER_assert(x=='a', "x=='a'"); + __CPROVER_assert(x=='b', "x=='b'"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-common-files/float_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/float_sensitivity_tests.c index 1f73fae4a6c..f45b9db843f 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/float_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/float_sensitivity_tests.c @@ -4,7 +4,7 @@ int main(int argc, char *argv[]) { // Test if we can represent constant floats float x=0.0; - assert(x==0.0); - assert(x==1.0); + __CPROVER_assert(x==0.0, "x==0.0"); + __CPROVER_assert(x==1.0, "x==1.0"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-common-files/int_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/int_sensitivity_tests.c index fab9e36038a..13845600396 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/int_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/int_sensitivity_tests.c @@ -10,45 +10,45 @@ int main(int argc, char *argv[]) { y=1; } - assert(x==0); - assert(x==1); - assert(x==y); + __CPROVER_assert(x==0, "x==0"); + __CPROVER_assert(x==1, "x==1"); + __CPROVER_assert(x==y, "x==y"); - assert(x<1); - assert(x<-1); - assert(x-1); - assert(x>1); - assert(x>y); + __CPROVER_assert(x>-1, "x>-1"); + __CPROVER_assert(x>1, "x>1"); + __CPROVER_assert(x>y, "x>y"); - assert(x!=1); - assert(x!=0); - assert(x!=y); + __CPROVER_assert(x!=1, "x!=1"); + __CPROVER_assert(x!=0, "x!=0"); + __CPROVER_assert(x!=y, "x!=y"); - assert(!(x==1)); - assert(!(x==0)); - assert(!(x==y)); + __CPROVER_assert(!(x==1), "!(x==1)"); + __CPROVER_assert(!(x==0), "!(x==0)"); + __CPROVER_assert(!(x==y), "!(x==y)"); // Test how well we can represent an int when it has more than one possible // value - assert(y<2); - assert(y>2); - assert(y==1); + __CPROVER_assert(y<2, "y<2"); + __CPROVER_assert(y>2, "y>2"); + __CPROVER_assert(y==1, "y==1"); // Try copying a variable and then modifying the original int z=x; x=10; - assert(z==0); - assert(z==10); + __CPROVER_assert(z==0, "z==0"); + __CPROVER_assert(z==10, "z==10"); // Test how we treat assertions in unreachable code x=0; if(0) { - assert(x==0); - assert(x==1); - assert(y==0); + __CPROVER_assert(x==0, "x==0"); + __CPROVER_assert(x==1, "x==1"); + __CPROVER_assert(y==0, "y==0"); } // Try merging two states with multiple variables @@ -67,11 +67,11 @@ int main(int argc, char *argv[]) } // all three asserts are unverifiable - assert(a1==0); - assert(a2==0); - assert(a3==0); - assert(a4==0); - assert(a5==0); + __CPROVER_assert(a1==0, "a1==0"); + __CPROVER_assert(a2==0, "a2==0"); + __CPROVER_assert(a3==0, "a3==0"); + __CPROVER_assert(a4==0, "a4==0"); + __CPROVER_assert(a5==0, "a5==0"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-common-files/pointer_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/pointer_sensitivity_tests.c index be328fa4a5d..5e6f1f1da73 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/pointer_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/pointer_sensitivity_tests.c @@ -10,31 +10,31 @@ int main(int argc, char *argv[]) int *x=&a; int *x2=&a; int *y=&b; - assert(x==&a); - assert(x==&b); - assert(x==x2); - assert(x==y); + __CPROVER_assert(x==&a, "x==&a"); + __CPROVER_assert(x==&b, "x==&b"); + __CPROVER_assert(x==x2, "x==x2"); + __CPROVER_assert(x==y, "x==y"); // Reading from a dereferenced pointer - assert(*x==0); - assert(*x==1); + __CPROVER_assert(*x==0, "*x==0"); + __CPROVER_assert(*x==1, "*x==1"); // Modify the referenced value and access it through the pointer again a=1; - assert(*x==1); - assert(*x==0); + __CPROVER_assert(*x==1, "*x==1"); + __CPROVER_assert(*x==0, "*x==0"); // Writing to a dereferenced pointer *x=2; - assert(a==2); - assert(a==0); + __CPROVER_assert(a==2, "a==2"); + __CPROVER_assert(a==0, "a==0"); // Conditionally reassign the pointer, but to the same value if(argc>2) { x=&a; } - assert(x==&a); + __CPROVER_assert(x==&a, "x==&a"); // Conditionally reassign the pointer, to a different value this time if(argc>3) @@ -45,9 +45,9 @@ int main(int argc, char *argv[]) { x=&c; } - assert(*x==0); - assert(x==&a); - assert(x==&b); + __CPROVER_assert(*x==0, "*x==0"); + __CPROVER_assert(x==&a, "x==&a"); + __CPROVER_assert(x==&b, "x==&b"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c index 21afdf52054..b379f048a58 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c @@ -6,39 +6,39 @@ int main(int argc, char *argv[]) // Test reading from an array using a pointer int a[3]={1, 2, 3}; int *p=a; - assert(p==&a[0]); + __CPROVER_assert(p==&a[0], "p==&a[0]"); - assert(*p==1); + __CPROVER_assert(*p==1, "*p==1"); - assert(p[1]==2); - assert(1[p]==2); + __CPROVER_assert(p[1]==2, "p[1]==2"); + __CPROVER_assert(1[p]==2, "1[p]==2"); - assert(*(p+1)==2); - assert(*(1+p)==2); + __CPROVER_assert(*(p+1)==2, "*(p+1)==2"); + __CPROVER_assert(*(1+p)==2, "*(1+p)==2"); - assert(*(p-1)==1); + __CPROVER_assert(*(p-1)==1, "*(p-1)==1"); // Test pointer arithmetic int *q=&a[1]; - assert(q==p+1); - assert(*q==2); + __CPROVER_assert(q==p+1, "q==p+1"); + __CPROVER_assert(*q==2, "*q==2"); // Test pointer diffs ptrdiff_t x=1; - assert(q-p==x); + __CPROVER_assert(q-p==x, "q-p==x"); // Test writing into an array using a pointer *q=4; - assert(a[1]==4); + __CPROVER_assert(a[1]==4, "a[1]==4"); p[1]=5; - assert(a[1]==5); + __CPROVER_assert(a[1]==5, "a[1]==5"); *(p+1)=6; - assert(a[1]==6); + __CPROVER_assert(a[1]==6, "a[1]==6"); *(1+p)=7; - assert(a[1]==7); + __CPROVER_assert(a[1]==7, "a[1]==7"); a[1]=2; @@ -56,23 +56,23 @@ int main(int argc, char *argv[]) // Test reading from an array using a pointer with more than one possible // value - assert(*r==2); - assert(*r==1); - assert(*s==0); - assert(*s==1); + __CPROVER_assert(*r==2, "*r==2"); + __CPROVER_assert(*r==1, "*r==1"); + __CPROVER_assert(*s==0, "*s==0"); + __CPROVER_assert(*s==1, "*s==1"); // Test pointer arithmetic with an unknown index int *t=&a[i]; - assert(t==p+i); + __CPROVER_assert(t==p+i, "t==p+i"); // Test pointer diffs with an unknown index ptrdiff_t y=i; - assert(t-p==y); + __CPROVER_assert(t-p==y, "t-p==y"); // Test writing into an array using a pointer with an unknown index *r=5; - assert(a[i]==5); - assert(a[1]==5); + __CPROVER_assert(a[i]==5, "a[i]==5"); + __CPROVER_assert(a[1]==5, "a[1]==5"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_pointer_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_pointer_sensitivity_tests.c index ee29a7059db..61aa658a2ec 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_pointer_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_pointer_sensitivity_tests.c @@ -9,16 +9,16 @@ int main(int argc, char *argv[]) int **x=&p; // Reading from a pointer to a pointer that's been dereferenced twice - assert(**x==0); - assert(**x==1); + __CPROVER_assert(**x==0, "**x==0"); + __CPROVER_assert(**x==1, "**x==1"); a=1; - assert(**x==1); - assert(**x==0); + __CPROVER_assert(**x==1, "**x==1"); + __CPROVER_assert(**x==0, "**x==0"); // Writing to a pointer to a pointer that's been dereferenced twice **x=2; - assert(a==2); - assert(a==1); + __CPROVER_assert(a==2, "a==2"); + __CPROVER_assert(a==1, "a==1"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_struct_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_struct_sensitivity_tests.c index e0092afae4a..52cef2e54e7 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_struct_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_struct_sensitivity_tests.c @@ -12,17 +12,17 @@ int main(int argc, char *argv[]) x.a=0; x.b=1.0; struct int_float *p=&x; - assert((*p).a==0); - assert((*p).a==1); + __CPROVER_assert((*p).a==0, "(*p).a==0"); + __CPROVER_assert((*p).a==1, "(*p).a==1"); // Test alternative syntax - assert(p->a==0); - assert(p->a==1); + __CPROVER_assert(p->a==0, "p->a==0"); + __CPROVER_assert(p->a==1, "p->a==1"); // Test writing to the struct through the pointer p->b=2.0; - assert(p->b==2.0); - assert(p->b==1.0); + __CPROVER_assert(p->b==2.0, "p->b==2.0"); + __CPROVER_assert(p->b==1.0, "p->b==1.0"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-common-files/struct_of_array_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/struct_of_array_sensitivity_tests.c index d5924b71ed7..646aa133183 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/struct_of_array_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/struct_of_array_sensitivity_tests.c @@ -15,19 +15,19 @@ int main(int argc, char *argv[]) x.b[0]=3.0f; x.b[1]=4.0f; x.b[2]=5.0f; - assert(x.a[0]==0); - assert(*(x.a+0)==0); - assert(*(0+x.a)==0); - assert(0[x.a]==0); + __CPROVER_assert(x.a[0]==0, "x.a[0]==0"); + __CPROVER_assert(*(x.a+0)==0, "*(x.a+0)==0"); + __CPROVER_assert(*(0+x.a)==0, "*(0+x.a)==0"); + __CPROVER_assert(0[x.a]==0, "0[x.a]==0"); // Test merging when there is only one value on both paths if(argc>2) { x.a[0]=0; } - assert(x.a[0]==0); - assert(x.a[1]==1); - assert(x.b[0]==3.0f); + __CPROVER_assert(x.a[0]==0, "x.a[0]==0"); + __CPROVER_assert(x.a[1]==1, "x.a[1]==1"); + __CPROVER_assert(x.b[0]==3.0f, "x.b[0]==3.0f"); // Test merging when there is one value for a and two values for b, to test if // we are representing them separately @@ -36,12 +36,12 @@ int main(int argc, char *argv[]) x.a[0]=0; x.b[2]=15.0f; } - assert(x.a[0]==0); - assert(x.a[1]==1); - assert(x.b[2]>0.0f); - assert(x.b[2]==15.0f); - assert(x.b[2]==1.0f); - assert(x.b[0]==3.0f); + __CPROVER_assert(x.a[0]==0, "x.a[0]==0"); + __CPROVER_assert(x.a[1]==1, "x.a[1]==1"); + __CPROVER_assert(x.b[2]>0.0f, "x.b[2]>0.0f"); + __CPROVER_assert(x.b[2]==15.0f, "x.b[2]==15.0f"); + __CPROVER_assert(x.b[2]==1.0f, "x.b[2]==1.0f"); + __CPROVER_assert(x.b[0]==3.0f, "x.b[0]==3.0f"); // Test merging when there are two values for a and b if(argc>4) @@ -49,10 +49,10 @@ int main(int argc, char *argv[]) x.a[0]=11; x.b[2]=25.0f; } - assert(x.a[0]<12); - assert(x.a[0]>2); - assert(x.a[0]==0); - assert(x.a[1]==1); + __CPROVER_assert(x.a[0]<12, "x.a[0]<12"); + __CPROVER_assert(x.a[0]>2, "x.a[0]>2"); + __CPROVER_assert(x.a[0]==0, "x.a[0]==0"); + __CPROVER_assert(x.a[1]==1, "x.a[1]==1"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-common-files/struct_of_pointer_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/struct_of_pointer_sensitivity_tests.c index 3cde8011c2b..19371f81644 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/struct_of_pointer_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/struct_of_pointer_sensitivity_tests.c @@ -18,14 +18,14 @@ int main(int argc, char *argv[]) struct int_float x; x.a=&a1; x.b=&b1; - assert(x.a==&a1); - assert(x.a==&a2); - assert(x.b==&b1); - assert(x.b==&b2); - assert(*x.a==0); - assert(*x.a==100); - assert(*x.b==10.0f); - assert(*x.b==110.0f); + __CPROVER_assert(x.a==&a1, "x.a==&a1"); + __CPROVER_assert(x.a==&a2, "x.a==&a2"); + __CPROVER_assert(x.b==&b1, "x.b==&b1"); + __CPROVER_assert(x.b==&b2, "x.b==&b2"); + __CPROVER_assert(*x.a==0, "*x.a==0"); + __CPROVER_assert(*x.a==100, "*x.a==100"); + __CPROVER_assert(*x.b==10.0f, "*x.b==10.0f"); + __CPROVER_assert(*x.b==110.0f, "*x.b==110.0f"); // Test merging when there is only one value on both paths if(argc>2) @@ -33,10 +33,10 @@ int main(int argc, char *argv[]) x.a=&a1; x.b=&b1; } - assert(x.a==&a1); - assert(x.a==&a2); - assert(*x.a==0); - assert(*x.a==100); + __CPROVER_assert(x.a==&a1, "x.a==&a1"); + __CPROVER_assert(x.a==&a2, "x.a==&a2"); + __CPROVER_assert(*x.a==0, "*x.a==0"); + __CPROVER_assert(*x.a==100, "*x.a==100"); // Test merging when there is one value for a and two values for b, to test if // we are representing them separately @@ -45,12 +45,12 @@ int main(int argc, char *argv[]) x.a=&a1; x.b=&b2; } - assert(x.a==&a1); - assert(x.b==&b2); - assert(x.b==&b3); - assert(*x.a==0); - assert(*x.b==11.0f); - assert(*x.b==12.0f); + __CPROVER_assert(x.a==&a1, "x.a==&a1"); + __CPROVER_assert(x.b==&b2, "x.b==&b2"); + __CPROVER_assert(x.b==&b3, "x.b==&b3"); + __CPROVER_assert(*x.a==0, "*x.a==0"); + __CPROVER_assert(*x.b==11.0f, "*x.b==11.0f"); + __CPROVER_assert(*x.b==12.0f, "*x.b==12.0f"); // Test merging when there are two values for a and b if(argc>4) @@ -58,14 +58,14 @@ int main(int argc, char *argv[]) x.a=&a2; x.b=&b3; } - assert(x.a==&a2); - assert(x.a==&a3); - assert(x.b==&b3); - assert(x.b==&b4); - assert(*x.a==1); - assert(*x.a==2); - assert(*x.b==12.0f); - assert(*x.b==13.0f); + __CPROVER_assert(x.a==&a2, "x.a==&a2"); + __CPROVER_assert(x.a==&a3, "x.a==&a3"); + __CPROVER_assert(x.b==&b3, "x.b==&b3"); + __CPROVER_assert(x.b==&b4, "x.b==&b4"); + __CPROVER_assert(*x.a==1, "*x.a==1"); + __CPROVER_assert(*x.a==2, "*x.a==2"); + __CPROVER_assert(*x.b==12.0f, "*x.b==12.0f"); + __CPROVER_assert(*x.b==13.0f, "*x.b==13.0f"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-common-files/struct_of_struct_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/struct_of_struct_sensitivity_tests.c index ac6a32a0086..dcaa72c4f34 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/struct_of_struct_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/struct_of_struct_sensitivity_tests.c @@ -18,16 +18,16 @@ int main(int argc, char *argv[]) x.s1.b=1.0; x.s2.a=2; x.s2.b=3.0f; - assert(x.s1.a==0); - assert(x.s2.b==3.0f); + __CPROVER_assert(x.s1.a==0, "x.s1.a==0"); + __CPROVER_assert(x.s2.b==3.0f, "x.s2.b==3.0f"); // Test merging when there is only one value on both paths if(argc>2) { x.s1.a=0; } - assert(x.s1.a==0); - assert(x.s1.a==10); + __CPROVER_assert(x.s1.a==0, "x.s1.a==0"); + __CPROVER_assert(x.s1.a==10, "x.s1.a==10"); // Test merging when there is one value for s1 and two values for s2, to test // if we are representing them separately @@ -36,9 +36,9 @@ int main(int argc, char *argv[]) x.s1.b=1.0f; x.s2.b=13.0f; } - assert(x.s1.b==1.0f); - assert(x.s2.b==3.0f); - assert(x.s2.b==0.0f); + __CPROVER_assert(x.s1.b==1.0f, "x.s1.b==1.0f"); + __CPROVER_assert(x.s2.b==3.0f, "x.s2.b==3.0f"); + __CPROVER_assert(x.s2.b==0.0f, "x.s2.b==0.0f"); // Test merging when there are two values for s1 and s2 if(argc>4) @@ -46,10 +46,10 @@ int main(int argc, char *argv[]) x.s1.a=20; x.s2.a=22; } - assert(x.s1.a==20); - assert(x.s1.a<30); - assert(x.s2.a==22); - assert(x.s2.a<30); + __CPROVER_assert(x.s1.a==20, "x.s1.a==20"); + __CPROVER_assert(x.s1.a<30, "x.s1.a<30"); + __CPROVER_assert(x.s2.a==22, "x.s2.a==22"); + __CPROVER_assert(x.s2.a<30, "x.s2.a<30"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-common-files/struct_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/struct_sensitivity_tests.c index a4ad229e34c..1d54f561265 100644 --- a/regression/goto-analyzer/sensitivity-test-common-files/struct_sensitivity_tests.c +++ b/regression/goto-analyzer/sensitivity-test-common-files/struct_sensitivity_tests.c @@ -11,8 +11,8 @@ int main(int argc, char *argv[]) struct int_float x={0, 1.0f}; x.a=0; x.b=1.0f; - assert(x.a==0); - assert(x.a==1); + __CPROVER_assert(x.a==0, "x.a==0"); + __CPROVER_assert(x.a==1, "x.a==1"); // Test merging when there is only one value on both paths if(argc>2) @@ -20,7 +20,7 @@ int main(int argc, char *argv[]) x.a=0; x.b=1.0f; } - assert(x.a==0); + __CPROVER_assert(x.a==0, "x.a==0"); // Test merging when there is one value for a and two values for b, to test if // we are representing them separately @@ -29,9 +29,9 @@ int main(int argc, char *argv[]) x.a=0; x.b=2.0f; } - assert(x.a==0); - assert(x.b>0.0f); - assert(x.b==1.0f); + __CPROVER_assert(x.a==0, "x.a==0"); + __CPROVER_assert(x.b>0.0f, "x.b>0.0f"); + __CPROVER_assert(x.b==1.0f, "x.b==1.0f"); // Test merging when there are two values for a and b if(argc>4) @@ -39,9 +39,9 @@ int main(int argc, char *argv[]) x.a=1; x.b=2.0f; } - assert(x.a<2); - assert(x.a>2); - assert(x.a==1); + __CPROVER_assert(x.a<2, "x.a<2"); + __CPROVER_assert(x.a>2, "x.a>2"); + __CPROVER_assert(x.a==1, "x.a==1"); return 0; } diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/test.desc index d7d2cf6516e..faad9ed3f87 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/test.desc @@ -3,71 +3,71 @@ sensitivity_test_constants_array_of_constants_array.c --variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion a\[1\]\[2\]==0: Success$ -^\[main.assertion.2\] .* assertion a\[1\]\[2\]==1: Failure \(if reachable\)$ -^\[main.assertion.3\] .* assertion b\[1\]\[2\]==5: Success$ -^\[main.assertion.4\] .* assertion b\[1\]\[2\]==0: Failure \(if reachable\)$ -^\[main.assertion.5\] .* assertion \*\(b\[1\]\+2\)==5: Success$ -^\[main.assertion.6\] .* assertion \*\(b\[1\]\+2\)==0: Failure \(if reachable\)$ -^\[main.assertion.7\] .* assertion \(\*\(b\+1\)\)\[2\]==5: Success$ -^\[main.assertion.8\] .* assertion \(\*\(b\+1\)\)\[2\]==0: Failure \(if reachable\)$ -^\[main.assertion.9\] .* assertion \*\(\*\(b\+1\)\+2\)==5: Success$ -^\[main.assertion.10\] .* assertion \*\(\*\(b\+1\)\+2\)==0: Failure \(if reachable\)$ -^\[main.assertion.11\] .* assertion 1\[b\]\[2\]==5: Success$ -^\[main.assertion.12\] .* assertion 1\[b\]\[2\]==0: Failure \(if reachable\)$ -^\[main.assertion.13\] .* assertion \*\(1\[b\]\+2\)==5: Success$ -^\[main.assertion.14\] .* assertion \*\(1\[b\]\+2\)==0: Failure \(if reachable\)$ -^\[main.assertion.15\] .* assertion \(\*\(1\+b\)\)\[2\]==5: Unknown$ -^\[main.assertion.16\] .* assertion \(\*\(1\+b\)\)\[2\]==0: Unknown$ -^\[main.assertion.17\] .* assertion \*\(\*\(1\+b\)\+2\)==5: Unknown$ -^\[main.assertion.18\] .* assertion \*\(\*\(1\+b\)\+2\)==0: Unknown$ -^\[main.assertion.19\] .* assertion 2\[1\[b\]\]==5: Success$ -^\[main.assertion.20\] .* assertion 2\[1\[b\]\]==0: Failure \(if reachable\)$ -^\[main.assertion.21\] .* assertion \*\(2\+1\[b\]\)==5: Unknown$ -^\[main.assertion.22\] .* assertion \*\(2\+1\[b\]\)==0: Unknown$ -^\[main.assertion.23\] .* assertion \*\(2\+\*\(1\+b\)\)==5: Unknown$ -^\[main.assertion.24\] .* assertion \*\(2\+\*\(1\+b\)\)==0: Unknown$ -^\[main.assertion.25\] .* assertion a\[0\]\[1\]==0: Success$ -^\[main.assertion.26\] .* assertion a\[0\]\[1\]==1: Failure \(if reachable\)$ -^\[main.assertion.27\] .* assertion a\[0\]\[2\]==0: Success$ -^\[main.assertion.28\] .* assertion b\[0\]\[1\]==2: Unknown$ -^\[main.assertion.29\] .* assertion b\[0\]\[1\]==3: Unknown$ -^\[main.assertion.30\] .* assertion b\[0\]\[2\]==2: Success$ -^\[main.assertion.31\] .* assertion a\[i\]\[1\]==0: Success$ -^\[main.assertion.32\] .* assertion a\[i\]\[1\]==1: Failure \(if reachable\)$ -^\[main.assertion.33\] .* assertion a\[1\]\[i\]==0: Success$ -^\[main.assertion.34\] .* assertion a\[1\]\[i\]==1: Failure \(if reachable\)$ -^\[main.assertion.35\] .* assertion a\[i\]\[i\]==0: Success$ -^\[main.assertion.36\] .* assertion a\[i\]\[i\]==1: Failure \(if reachable\)$ -^\[main.assertion.37\] .* assertion a\[j\]\[1\]==0: Unknown$ -^\[main.assertion.38\] .* assertion a\[j\]\[1\]==1: Unknown$ -^\[main.assertion.39\] .* assertion a\[1\]\[j\]==0: Unknown$ -^\[main.assertion.40\] .* assertion a\[1\]\[j\]==1: Unknown$ -^\[main.assertion.41\] .* assertion a\[j\]\[j\]==0: Unknown$ -^\[main.assertion.42\] .* assertion a\[j\]\[j\]==1: Unknown$ -^\[main.assertion.43\] .* assertion b\[i\]\[1\]==1: Success$ -^\[main.assertion.44\] .* assertion b\[i\]\[1\]==11: Failure \(if reachable\)$ -^\[main.assertion.45\] .* assertion b\[1\]\[i\]==3: Success$ -^\[main.assertion.46\] .* assertion b\[1\]\[i\]==11: Failure \(if reachable\)$ -^\[main.assertion.47\] .* assertion b\[i\]\[i\]==0: Success$ -^\[main.assertion.48\] .* assertion b\[i\]\[i\]==11: Failure \(if reachable\)$ -^\[main.assertion.49\] .* assertion b\[j\]\[1\]==1: Unknown$ -^\[main.assertion.50\] .* assertion b\[j\]\[1\]==11: Unknown$ -^\[main.assertion.51\] .* assertion b\[1\]\[j\]==3: Unknown$ -^\[main.assertion.52\] .* assertion b\[1\]\[j\]==11: Unknown$ -^\[main.assertion.53\] .* assertion b\[j\]\[j\]==0: Unknown$ -^\[main.assertion.54\] .* assertion b\[j\]\[j\]==11: Unknown$ -^\[main.assertion.55\] .* assertion a\[100\]\[0\]==0: Unknown$ -^\[main.assertion.56\] .* assertion a\[0\]\[100\]==0: Unknown$ -^\[main.assertion.57\] .* assertion c==0: Success$ -^\[main.assertion.58\] .* assertion c==0: Success$ -^\[main.assertion.59\] .* assertion ei\[0\]\[1\]==1: Success$ -^\[main.assertion.60\] .* assertion ei\[0\]\[1\]==0: Failure \(if reachable\)$ -^\[main.assertion.61\] .* assertion ei\[2\]\[1\]==0: Success$ -^\[main.assertion.62\] .* assertion ei\[2\]\[1\]==1: Failure \(if reachable\)$ -^\[main.assertion.63\] .* assertion ej\[0\]\[1\]==0: Unknown$ -^\[main.assertion.64\] .* assertion ej\[2\]\[1\]==0: Unknown$ -^\[main.assertion.65\] .* assertion ek\[0\]\[1\]==0: Unknown$ -^\[main.assertion.66\] .* assertion c==0: Success$ +^\[main.assertion.1\] .* a\[1\]\[2\]==0: Success$ +^\[main.assertion.2\] .* a\[1\]\[2\]==1: Failure \(if reachable\)$ +^\[main.assertion.3\] .* b\[1\]\[2\]==5: Success$ +^\[main.assertion.4\] .* b\[1\]\[2\]==0: Failure \(if reachable\)$ +^\[main.assertion.5\] .* \*\(b\[1\]\+2\)==5: Success$ +^\[main.assertion.6\] .* \*\(b\[1\]\+2\)==0: Failure \(if reachable\)$ +^\[main.assertion.7\] .* \(\*\(b\+1\)\)\[2\]==5: Success$ +^\[main.assertion.8\] .* \(\*\(b\+1\)\)\[2\]==0: Failure \(if reachable\)$ +^\[main.assertion.9\] .* \*\(\*\(b\+1\)\+2\)==5: Success$ +^\[main.assertion.10\] .* \*\(\*\(b\+1\)\+2\)==0: Failure \(if reachable\)$ +^\[main.assertion.11\] .* 1\[b\]\[2\]==5: Success$ +^\[main.assertion.12\] .* 1\[b\]\[2\]==0: Failure \(if reachable\)$ +^\[main.assertion.13\] .* \*\(1\[b\]\+2\)==5: Success$ +^\[main.assertion.14\] .* \*\(1\[b\]\+2\)==0: Failure \(if reachable\)$ +^\[main.assertion.15\] .* \(\*\(1\+b\)\)\[2\]==5: Unknown$ +^\[main.assertion.16\] .* \(\*\(1\+b\)\)\[2\]==0: Unknown$ +^\[main.assertion.17\] .* \*\(\*\(1\+b\)\+2\)==5: Unknown$ +^\[main.assertion.18\] .* \*\(\*\(1\+b\)\+2\)==0: Unknown$ +^\[main.assertion.19\] .* 2\[1\[b\]\]==5: Success$ +^\[main.assertion.20\] .* 2\[1\[b\]\]==0: Failure \(if reachable\)$ +^\[main.assertion.21\] .* \*\(2\+1\[b\]\)==5: Unknown$ +^\[main.assertion.22\] .* \*\(2\+1\[b\]\)==0: Unknown$ +^\[main.assertion.23\] .* \*\(2\+\*\(1\+b\)\)==5: Unknown$ +^\[main.assertion.24\] .* \*\(2\+\*\(1\+b\)\)==0: Unknown$ +^\[main.assertion.25\] .* a\[0\]\[1\]==0: Success$ +^\[main.assertion.26\] .* a\[0\]\[1\]==1: Failure \(if reachable\)$ +^\[main.assertion.27\] .* a\[0\]\[2\]==0: Success$ +^\[main.assertion.28\] .* b\[0\]\[1\]==2: Unknown$ +^\[main.assertion.29\] .* b\[0\]\[1\]==3: Unknown$ +^\[main.assertion.30\] .* b\[0\]\[2\]==2: Success$ +^\[main.assertion.31\] .* a\[i\]\[1\]==0: Success$ +^\[main.assertion.32\] .* a\[i\]\[1\]==1: Failure \(if reachable\)$ +^\[main.assertion.33\] .* a\[1\]\[i\]==0: Success$ +^\[main.assertion.34\] .* a\[1\]\[i\]==1: Failure \(if reachable\)$ +^\[main.assertion.35\] .* a\[i\]\[i\]==0: Success$ +^\[main.assertion.36\] .* a\[i\]\[i\]==1: Failure \(if reachable\)$ +^\[main.assertion.37\] .* a\[j\]\[1\]==0: Unknown$ +^\[main.assertion.38\] .* a\[j\]\[1\]==1: Unknown$ +^\[main.assertion.39\] .* a\[1\]\[j\]==0: Unknown$ +^\[main.assertion.40\] .* a\[1\]\[j\]==1: Unknown$ +^\[main.assertion.41\] .* a\[j\]\[j\]==0: Unknown$ +^\[main.assertion.42\] .* a\[j\]\[j\]==1: Unknown$ +^\[main.assertion.43\] .* b\[i\]\[1\]==1: Success$ +^\[main.assertion.44\] .* b\[i\]\[1\]==11: Failure \(if reachable\)$ +^\[main.assertion.45\] .* b\[1\]\[i\]==3: Success$ +^\[main.assertion.46\] .* b\[1\]\[i\]==11: Failure \(if reachable\)$ +^\[main.assertion.47\] .* b\[i\]\[i\]==0: Success$ +^\[main.assertion.48\] .* b\[i\]\[i\]==11: Failure \(if reachable\)$ +^\[main.assertion.49\] .* b\[j\]\[1\]==1: Unknown$ +^\[main.assertion.50\] .* b\[j\]\[1\]==11: Unknown$ +^\[main.assertion.51\] .* b\[1\]\[j\]==3: Unknown$ +^\[main.assertion.52\] .* b\[1\]\[j\]==11: Unknown$ +^\[main.assertion.53\] .* b\[j\]\[j\]==0: Unknown$ +^\[main.assertion.54\] .* b\[j\]\[j\]==11: Unknown$ +^\[main.assertion.55\] .* a\[100\]\[0\]==0: Unknown$ +^\[main.assertion.56\] .* a\[0\]\[100\]==0: Unknown$ +^\[main.assertion.57\] .* c==0: Success$ +^\[main.assertion.58\] .* c==0: Success$ +^\[main.assertion.59\] .* ei\[0\]\[1\]==1: Success$ +^\[main.assertion.60\] .* ei\[0\]\[1\]==0: Failure \(if reachable\)$ +^\[main.assertion.61\] .* ei\[2\]\[1\]==0: Success$ +^\[main.assertion.62\] .* ei\[2\]\[1\]==1: Failure \(if reachable\)$ +^\[main.assertion.63\] .* ej\[0\]\[1\]==0: Unknown$ +^\[main.assertion.64\] .* ej\[2\]\[1\]==0: Unknown$ +^\[main.assertion.65\] .* ek\[0\]\[1\]==0: Unknown$ +^\[main.assertion.66\] .* c==0: Success$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc index 23a01dec7f8..6c1efef50a2 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc @@ -3,73 +3,73 @@ sensitivity_test_constants_array_of_constants_pointer.c --variable --arrays --pointers --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion a\[1\]==&a0: Success$ -^\[main.assertion.2\] .* assertion a\[1\]==&a3: Failure \(if reachable\)$ -^\[main.assertion.3\] .* assertion \*a\[1\]==0: Success$ -^\[main.assertion.4\] .* assertion \*a\[1\]==3: Failure \(if reachable\)$ -^\[main.assertion.5\] .* assertion b\[1\]==&b1: Success$ -^\[main.assertion.6\] .* assertion b\[1\]==&b3: Failure \(if reachable\)$ -^\[main.assertion.7\] .* assertion \*b\[1\]==11: Success$ -^\[main.assertion.8\] .* assertion \*b\[1\]==13: Failure \(if reachable\)$ -^\[main.assertion.9\] .* assertion \*\(b\+1\)==&b1: Success$ -^\[main.assertion.10\] .* assertion \*\(b\+1\)==&b3: Failure \(if reachable\)$ -^\[main.assertion.11\] .* assertion \*\(1\+b\)==&b1: Unknown$ -^\[main.assertion.12\] .* assertion \*\(1\+b\)==&b3: Unknown$ -^\[main.assertion.13\] .* assertion 1\[b\]==&b1: Success$ -^\[main.assertion.14\] .* assertion 1\[b\]==&b3: Failure \(if reachable\)$ -^\[main.assertion.15\] .* assertion \*\*\(b\+1\)==11: Success$ -^\[main.assertion.16\] .* assertion \*\*\(b\+1\)==13: Failure \(if reachable\)$ -^\[main.assertion.17\] .* assertion \*\*\(1\+b\)==11: Unknown$ -^\[main.assertion.18\] .* assertion \*\*\(1\+b\)==13: Unknown$ -^\[main.assertion.19\] .* assertion \*1\[b\]==11: Success$ -^\[main.assertion.20\] .* assertion \*1\[b\]==13: Failure \(if reachable\)$ -^\[main.assertion.21\] .* assertion c\[0\]==&c0: Unknown$ -^\[main.assertion.22\] .* assertion c\[0\]==&c3: Unknown$ -^\[main.assertion.23\] .* assertion d\[0\]==&d0: Unknown$ -^\[main.assertion.24\] .* assertion d\[0\]==&d3: Unknown$ -^\[main.assertion.25\] .* assertion \*c\[0\]==20: Unknown$ -^\[main.assertion.26\] .* assertion \*c\[0\]==23: Unknown$ -^\[main.assertion.27\] .* assertion \*d\[0\]==30: Unknown$ -^\[main.assertion.28\] .* assertion \*d\[0\]==33: Unknown$ -^\[main.assertion.29\] .* assertion a\[i\]==&a0: Success$ -^\[main.assertion.30\] .* assertion a\[i\]==&a3: Failure \(if reachable\)$ -^\[main.assertion.31\] .* assertion a\[j\]==&a0: Unknown$ -^\[main.assertion.32\] .* assertion a\[j\]==&a3: Unknown$ -^\[main.assertion.33\] .* assertion \*a\[i\]==0: Success$ -^\[main.assertion.34\] .* assertion \*a\[i\]==3: Failure \(if reachable\)$ -^\[main.assertion.35\] .* assertion \*a\[j\]==0: Unknown$ -^\[main.assertion.36\] .* assertion \*a\[j\]==3: Unknown$ -^\[main.assertion.37\] .* assertion b\[i\]==&b0: Success$ -^\[main.assertion.38\] .* assertion b\[i\]==&b1: Failure \(if reachable\)$ -^\[main.assertion.39\] .* assertion b\[j\]==&b0: Unknown$ -^\[main.assertion.40\] .* assertion b\[j\]==&b3: Unknown$ -^\[main.assertion.41\] .* assertion \*b\[i\]==10: Success$ -^\[main.assertion.42\] .* assertion \*b\[i\]==11: Failure \(if reachable\)$ -^\[main.assertion.43\] .* assertion \*b\[j\]==10: Unknown$ -^\[main.assertion.44\] .* assertion \*b\[j\]==13: Unknown$ -^\[main.assertion.45\] .* assertion a\[100\]==&a2: Unknown$ -^\[main.assertion.46\] .* assertion \*a\[100\]==2: Unknown$ -^\[main.assertion.47\] .* assertion b\[1\]==&b1: Success$ -^\[main.assertion.48\] .* assertion \*b\[1\]==11: Success$ -^\[main.assertion.49\] .* assertion ei\[0\]==&ei1: Success$ -^\[main.assertion.50\] .* assertion ei\[0\]==&ei0: Failure \(if reachable\)$ -^\[main.assertion.51\] .* assertion ei\[2\]==&ei0: Success$ -^\[main.assertion.52\] .* assertion ei\[2\]==&ei1: Failure \(if reachable\)$ -^\[main.assertion.53\] .* assertion \*ei\[0\]==41: Success$ -^\[main.assertion.54\] .* assertion \*ei\[0\]==40: Failure \(if reachable\)$ -^\[main.assertion.55\] .* assertion \*ei\[2\]==40: Success$ -^\[main.assertion.56\] .* assertion \*ei\[2\]==41: Failure \(if reachable\)$ -^\[main.assertion.57\] .* assertion ej\[0\]==&ej0: Unknown$ -^\[main.assertion.58\] .* assertion ej\[2\]==&ej0: Unknown$ -^\[main.assertion.59\] .* assertion ej\[2\]==&ej1: Unknown$ -^\[main.assertion.60\] .* assertion \*ej\[0\]==50: Unknown$ -^\[main.assertion.61\] .* assertion \*ej\[2\]==50: Unknown$ -^\[main.assertion.62\] .* assertion \*ej\[2\]==51: Unknown$ -^\[main.assertion.63\] .* assertion ek\[0\]==&ek0: Unknown$ -^\[main.assertion.64\] .* assertion \*ek\[0\]==60: Unknown$ -^\[main\.assertion\.65\] .* assertion \*ps\[0\]==4: Success$ -^\[main\.assertion\.66\] .* assertion \*ps\[1\]==4: Unknown$ -^\[main\.assertion\.67\] .* assertion x==4: Success$ -^\[main\.assertion\.68\] .* assertion y==4: Unknown$ +^\[main.assertion.1\] .* a\[1\]==&a0: Success$ +^\[main.assertion.2\] .* a\[1\]==&a3: Failure \(if reachable\)$ +^\[main.assertion.3\] .* \*a\[1\]==0: Success$ +^\[main.assertion.4\] .* \*a\[1\]==3: Failure \(if reachable\)$ +^\[main.assertion.5\] .* b\[1\]==&b1: Success$ +^\[main.assertion.6\] .* b\[1\]==&b3: Failure \(if reachable\)$ +^\[main.assertion.7\] .* \*b\[1\]==11: Success$ +^\[main.assertion.8\] .* \*b\[1\]==13: Failure \(if reachable\)$ +^\[main.assertion.9\] .* \*\(b\+1\)==&b1: Success$ +^\[main.assertion.10\] .* \*\(b\+1\)==&b3: Failure \(if reachable\)$ +^\[main.assertion.11\] .* \*\(1\+b\)==&b1: Unknown$ +^\[main.assertion.12\] .* \*\(1\+b\)==&b3: Unknown$ +^\[main.assertion.13\] .* 1\[b\]==&b1: Success$ +^\[main.assertion.14\] .* 1\[b\]==&b3: Failure \(if reachable\)$ +^\[main.assertion.15\] .* \*\*\(b\+1\)==11: Success$ +^\[main.assertion.16\] .* \*\*\(b\+1\)==13: Failure \(if reachable\)$ +^\[main.assertion.17\] .* \*\*\(1\+b\)==11: Unknown$ +^\[main.assertion.18\] .* \*\*\(1\+b\)==13: Unknown$ +^\[main.assertion.19\] .* \*1\[b\]==11: Success$ +^\[main.assertion.20\] .* \*1\[b\]==13: Failure \(if reachable\)$ +^\[main.assertion.21\] .* c\[0\]==&c0: Unknown$ +^\[main.assertion.22\] .* c\[0\]==&c3: Unknown$ +^\[main.assertion.23\] .* d\[0\]==&d0: Unknown$ +^\[main.assertion.24\] .* d\[0\]==&d3: Unknown$ +^\[main.assertion.25\] .* \*c\[0\]==20: Unknown$ +^\[main.assertion.26\] .* \*c\[0\]==23: Unknown$ +^\[main.assertion.27\] .* \*d\[0\]==30: Unknown$ +^\[main.assertion.28\] .* \*d\[0\]==33: Unknown$ +^\[main.assertion.29\] .* a\[i\]==&a0: Success$ +^\[main.assertion.30\] .* a\[i\]==&a3: Failure \(if reachable\)$ +^\[main.assertion.31\] .* a\[j\]==&a0: Unknown$ +^\[main.assertion.32\] .* a\[j\]==&a3: Unknown$ +^\[main.assertion.33\] .* \*a\[i\]==0: Success$ +^\[main.assertion.34\] .* \*a\[i\]==3: Failure \(if reachable\)$ +^\[main.assertion.35\] .* \*a\[j\]==0: Unknown$ +^\[main.assertion.36\] .* \*a\[j\]==3: Unknown$ +^\[main.assertion.37\] .* b\[i\]==&b0: Success$ +^\[main.assertion.38\] .* b\[i\]==&b1: Failure \(if reachable\)$ +^\[main.assertion.39\] .* b\[j\]==&b0: Unknown$ +^\[main.assertion.40\] .* b\[j\]==&b3: Unknown$ +^\[main.assertion.41\] .* \*b\[i\]==10: Success$ +^\[main.assertion.42\] .* \*b\[i\]==11: Failure \(if reachable\)$ +^\[main.assertion.43\] .* \*b\[j\]==10: Unknown$ +^\[main.assertion.44\] .* \*b\[j\]==13: Unknown$ +^\[main.assertion.45\] .* a\[100\]==&a2: Unknown$ +^\[main.assertion.46\] .* \*a\[100\]==2: Unknown$ +^\[main.assertion.47\] .* b\[1\]==&b1: Success$ +^\[main.assertion.48\] .* \*b\[1\]==11: Success$ +^\[main.assertion.49\] .* ei\[0\]==&ei1: Success$ +^\[main.assertion.50\] .* ei\[0\]==&ei0: Failure \(if reachable\)$ +^\[main.assertion.51\] .* ei\[2\]==&ei0: Success$ +^\[main.assertion.52\] .* ei\[2\]==&ei1: Failure \(if reachable\)$ +^\[main.assertion.53\] .* \*ei\[0\]==41: Success$ +^\[main.assertion.54\] .* \*ei\[0\]==40: Failure \(if reachable\)$ +^\[main.assertion.55\] .* \*ei\[2\]==40: Success$ +^\[main.assertion.56\] .* \*ei\[2\]==41: Failure \(if reachable\)$ +^\[main.assertion.57\] .* ej\[0\]==&ej0: Unknown$ +^\[main.assertion.58\] .* ej\[2\]==&ej0: Unknown$ +^\[main.assertion.59\] .* ej\[2\]==&ej1: Unknown$ +^\[main.assertion.60\] .* \*ej\[0\]==50: Unknown$ +^\[main.assertion.61\] .* \*ej\[2\]==50: Unknown$ +^\[main.assertion.62\] .* \*ej\[2\]==51: Unknown$ +^\[main.assertion.63\] .* ek\[0\]==&ek0: Unknown$ +^\[main.assertion.64\] .* \*ek\[0\]==60: Unknown$ +^\[main\.assertion\.65\] .* \*ps\[0\]==4: Success$ +^\[main\.assertion\.66\] .* \*ps\[1\]==4: Unknown$ +^\[main\.assertion\.67\] .* x==4: Success$ +^\[main\.assertion\.68\] .* y==4: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc index 51c41aff0a9..0ed4c8ad55a 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc @@ -3,73 +3,73 @@ sensitivity_test_constants_array_of_two_value_pointer.c --variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion a\[1\]==&a0: Unknown$ -^\[main.assertion.2\] .* assertion a\[1\]==&a3: Unknown$ -^\[main.assertion.3\] .* assertion \*a\[1\]==0: Unknown$ -^\[main.assertion.4\] .* assertion \*a\[1\]==3: Unknown$ -^\[main.assertion.5\] .* assertion b\[1\]==&b1: Unknown$ -^\[main.assertion.6\] .* assertion b\[1\]==&b3: Unknown$ -^\[main.assertion.7\] .* assertion \*b\[1\]==11: Unknown$ -^\[main.assertion.8\] .* assertion \*b\[1\]==13: Unknown$ -^\[main.assertion.9\] .* assertion \*\(b\+1\)==&b1: Unknown$ -^\[main.assertion.10\] .* assertion \*\(b\+1\)==&b3: Unknown$ -^\[main.assertion.11\] .* assertion \*\(1\+b\)==&b1: Unknown$ -^\[main.assertion.12\] .* assertion \*\(1\+b\)==&b3: Unknown$ -^\[main.assertion.13\] .* assertion 1\[b\]==&b1: Unknown$ -^\[main.assertion.14\] .* assertion 1\[b\]==&b3: Unknown$ -^\[main.assertion.15\] .* assertion \*\*\(b\+1\)==11: Unknown$ -^\[main.assertion.16\] .* assertion \*\*\(b\+1\)==13: Unknown$ -^\[main.assertion.17\] .* assertion \*\*\(1\+b\)==11: Unknown$ -^\[main.assertion.18\] .* assertion \*\*\(1\+b\)==13: Unknown$ -^\[main.assertion.19\] .* assertion \*1\[b\]==11: Unknown$ -^\[main.assertion.20\] .* assertion \*1\[b\]==13: Unknown$ -^\[main.assertion.21\] .* assertion c\[0\]==&c0: Unknown$ -^\[main.assertion.22\] .* assertion c\[0\]==&c3: Unknown$ -^\[main.assertion.23\] .* assertion d\[0\]==&d0: Unknown$ -^\[main.assertion.24\] .* assertion d\[0\]==&d3: Unknown$ -^\[main.assertion.25\] .* assertion \*c\[0\]==20: Unknown$ -^\[main.assertion.26\] .* assertion \*c\[0\]==23: Unknown$ -^\[main.assertion.27\] .* assertion \*d\[0\]==30: Unknown$ -^\[main.assertion.28\] .* assertion \*d\[0\]==33: Unknown$ -^\[main.assertion.29\] .* assertion a\[i\]==&a0: Unknown$ -^\[main.assertion.30\] .* assertion a\[i\]==&a3: Unknown$ -^\[main.assertion.31\] .* assertion a\[j\]==&a0: Unknown$ -^\[main.assertion.32\] .* assertion a\[j\]==&a3: Unknown$ -^\[main.assertion.33\] .* assertion \*a\[i\]==0: Unknown$ -^\[main.assertion.34\] .* assertion \*a\[i\]==3: Unknown$ -^\[main.assertion.35\] .* assertion \*a\[j\]==0: Unknown$ -^\[main.assertion.36\] .* assertion \*a\[j\]==3: Unknown$ -^\[main.assertion.37\] .* assertion b\[i\]==&b0: Unknown$ -^\[main.assertion.38\] .* assertion b\[i\]==&b1: Unknown$ -^\[main.assertion.39\] .* assertion b\[j\]==&b0: Unknown$ -^\[main.assertion.40\] .* assertion b\[j\]==&b3: Unknown$ -^\[main.assertion.41\] .* assertion \*b\[i\]==10: Unknown$ -^\[main.assertion.42\] .* assertion \*b\[i\]==11: Unknown$ -^\[main.assertion.43\] .* assertion \*b\[j\]==10: Unknown$ -^\[main.assertion.44\] .* assertion \*b\[j\]==13: Unknown$ -^\[main.assertion.45\] .* assertion a\[100\]==&a2: Unknown$ -^\[main.assertion.46\] .* assertion \*a\[100\]==2: Unknown$ -^\[main.assertion.47\] .* assertion b\[1\]==&b1: Unknown$ -^\[main.assertion.48\] .* assertion \*b\[1\]==11: Unknown$ -^\[main.assertion.49\] .* assertion ei\[0\]==&ei1: Unknown$ -^\[main.assertion.50\] .* assertion ei\[0\]==&ei0: Unknown$ -^\[main.assertion.51\] .* assertion ei\[2\]==&ei0: Unknown$ -^\[main.assertion.52\] .* assertion ei\[2\]==&ei1: Unknown$ -^\[main.assertion.53\] .* assertion \*ei\[0\]==41: Unknown$ -^\[main.assertion.54\] .* assertion \*ei\[0\]==40: Unknown$ -^\[main.assertion.55\] .* assertion \*ei\[2\]==40: Unknown$ -^\[main.assertion.56\] .* assertion \*ei\[2\]==41: Unknown$ -^\[main.assertion.57\] .* assertion ej\[0\]==&ej0: Unknown$ -^\[main.assertion.58\] .* assertion ej\[2\]==&ej0: Unknown$ -^\[main.assertion.59\] .* assertion ej\[2\]==&ej1: Unknown$ -^\[main.assertion.60\] .* assertion \*ej\[0\]==50: Unknown$ -^\[main.assertion.61\] .* assertion \*ej\[2\]==50: Unknown$ -^\[main.assertion.62\] .* assertion \*ej\[2\]==51: Unknown$ -^\[main.assertion.63\] .* assertion ek\[0\]==&ek0: Unknown$ -^\[main.assertion.64\] .* assertion \*ek\[0\]==60: Unknown$ -^\[main\.assertion\.65\] .* assertion \*ps\[0\]==4: Unknown$ -^\[main\.assertion\.66\] .* assertion \*ps\[1\]==4: Unknown$ -^\[main\.assertion\.67\] .* assertion x==4: Unknown$ -^\[main\.assertion\.68\] .* assertion y==4: Unknown$ +^\[main.assertion.1\] .* a\[1\]==&a0: Unknown$ +^\[main.assertion.2\] .* a\[1\]==&a3: Unknown$ +^\[main.assertion.3\] .* \*a\[1\]==0: Unknown$ +^\[main.assertion.4\] .* \*a\[1\]==3: Unknown$ +^\[main.assertion.5\] .* b\[1\]==&b1: Unknown$ +^\[main.assertion.6\] .* b\[1\]==&b3: Unknown$ +^\[main.assertion.7\] .* \*b\[1\]==11: Unknown$ +^\[main.assertion.8\] .* \*b\[1\]==13: Unknown$ +^\[main.assertion.9\] .* \*\(b\+1\)==&b1: Unknown$ +^\[main.assertion.10\] .* \*\(b\+1\)==&b3: Unknown$ +^\[main.assertion.11\] .* \*\(1\+b\)==&b1: Unknown$ +^\[main.assertion.12\] .* \*\(1\+b\)==&b3: Unknown$ +^\[main.assertion.13\] .* 1\[b\]==&b1: Unknown$ +^\[main.assertion.14\] .* 1\[b\]==&b3: Unknown$ +^\[main.assertion.15\] .* \*\*\(b\+1\)==11: Unknown$ +^\[main.assertion.16\] .* \*\*\(b\+1\)==13: Unknown$ +^\[main.assertion.17\] .* \*\*\(1\+b\)==11: Unknown$ +^\[main.assertion.18\] .* \*\*\(1\+b\)==13: Unknown$ +^\[main.assertion.19\] .* \*1\[b\]==11: Unknown$ +^\[main.assertion.20\] .* \*1\[b\]==13: Unknown$ +^\[main.assertion.21\] .* c\[0\]==&c0: Unknown$ +^\[main.assertion.22\] .* c\[0\]==&c3: Unknown$ +^\[main.assertion.23\] .* d\[0\]==&d0: Unknown$ +^\[main.assertion.24\] .* d\[0\]==&d3: Unknown$ +^\[main.assertion.25\] .* \*c\[0\]==20: Unknown$ +^\[main.assertion.26\] .* \*c\[0\]==23: Unknown$ +^\[main.assertion.27\] .* \*d\[0\]==30: Unknown$ +^\[main.assertion.28\] .* \*d\[0\]==33: Unknown$ +^\[main.assertion.29\] .* a\[i\]==&a0: Unknown$ +^\[main.assertion.30\] .* a\[i\]==&a3: Unknown$ +^\[main.assertion.31\] .* a\[j\]==&a0: Unknown$ +^\[main.assertion.32\] .* a\[j\]==&a3: Unknown$ +^\[main.assertion.33\] .* \*a\[i\]==0: Unknown$ +^\[main.assertion.34\] .* \*a\[i\]==3: Unknown$ +^\[main.assertion.35\] .* \*a\[j\]==0: Unknown$ +^\[main.assertion.36\] .* \*a\[j\]==3: Unknown$ +^\[main.assertion.37\] .* b\[i\]==&b0: Unknown$ +^\[main.assertion.38\] .* b\[i\]==&b1: Unknown$ +^\[main.assertion.39\] .* b\[j\]==&b0: Unknown$ +^\[main.assertion.40\] .* b\[j\]==&b3: Unknown$ +^\[main.assertion.41\] .* \*b\[i\]==10: Unknown$ +^\[main.assertion.42\] .* \*b\[i\]==11: Unknown$ +^\[main.assertion.43\] .* \*b\[j\]==10: Unknown$ +^\[main.assertion.44\] .* \*b\[j\]==13: Unknown$ +^\[main.assertion.45\] .* a\[100\]==&a2: Unknown$ +^\[main.assertion.46\] .* \*a\[100\]==2: Unknown$ +^\[main.assertion.47\] .* b\[1\]==&b1: Unknown$ +^\[main.assertion.48\] .* \*b\[1\]==11: Unknown$ +^\[main.assertion.49\] .* ei\[0\]==&ei1: Unknown$ +^\[main.assertion.50\] .* ei\[0\]==&ei0: Unknown$ +^\[main.assertion.51\] .* ei\[2\]==&ei0: Unknown$ +^\[main.assertion.52\] .* ei\[2\]==&ei1: Unknown$ +^\[main.assertion.53\] .* \*ei\[0\]==41: Unknown$ +^\[main.assertion.54\] .* \*ei\[0\]==40: Unknown$ +^\[main.assertion.55\] .* \*ei\[2\]==40: Unknown$ +^\[main.assertion.56\] .* \*ei\[2\]==41: Unknown$ +^\[main.assertion.57\] .* ej\[0\]==&ej0: Unknown$ +^\[main.assertion.58\] .* ej\[2\]==&ej0: Unknown$ +^\[main.assertion.59\] .* ej\[2\]==&ej1: Unknown$ +^\[main.assertion.60\] .* \*ej\[0\]==50: Unknown$ +^\[main.assertion.61\] .* \*ej\[2\]==50: Unknown$ +^\[main.assertion.62\] .* \*ej\[2\]==51: Unknown$ +^\[main.assertion.63\] .* ek\[0\]==&ek0: Unknown$ +^\[main.assertion.64\] .* \*ek\[0\]==60: Unknown$ +^\[main\.assertion\.65\] .* \*ps\[0\]==4: Unknown$ +^\[main\.assertion\.66\] .* \*ps\[1\]==4: Unknown$ +^\[main\.assertion\.67\] .* x==4: Unknown$ +^\[main\.assertion\.68\] .* y==4: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array/test.desc index 624689e233f..01c9d186194 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array/test.desc @@ -3,37 +3,37 @@ sensitivity_test_constants_array.c --variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion a\[1\]==0: Success$ -^\[main.assertion.2\] .* assertion a\[1\]==1: Failure \(if reachable\)$ -^\[main.assertion.3\] .* assertion b\[1\]==0: Success$ -^\[main.assertion.4\] .* assertion b\[1\]==1: Failure \(if reachable\)$ -^\[main.assertion.5\] .* assertion \*\(b\+1\)==0: Success$ -^\[main.assertion.6\] .* assertion \*\(b\+1\)==1: Failure \(if reachable\)$ -^\[main.assertion.7\] .* assertion \*\(1\+b\)==0: Unknown$ -^\[main.assertion.8\] .* assertion \*\(1\+b\)==1: Unknown$ -^\[main.assertion.9\] .* assertion 1\[b\]==0: Success$ -^\[main.assertion.10\] .* assertion 1\[b\]==1: Failure \(if reachable\)$ -^\[main.assertion.11\] .* assertion c\[0\]==0: Success$ -^\[main.assertion.12\] .* assertion c\[0\]==1: Failure \(if reachable\)$ -^\[main.assertion.13\] .* assertion d\[0\]==0: Unknown$ -^\[main.assertion.14\] .* assertion d\[0\]==2: Unknown$ -^\[main.assertion.15\] .* assertion d\[1\]==0: Success$ -^\[main.assertion.16\] .* assertion a\[i\]==0: Success$ -^\[main.assertion.17\] .* assertion a\[i\]==1: Failure \(if reachable\)$ -^\[main.assertion.18\] .* assertion a\[j\]==0: Unknown$ -^\[main.assertion.19\] .* assertion a\[j\]==1: Unknown$ -^\[main.assertion.20\] .* assertion b\[i\]==1: Success$ -^\[main.assertion.21\] .* assertion b\[i\]==0: Failure \(if reachable\)$ -^\[main.assertion.22\] .* assertion b\[j\]==0: Unknown$ -^\[main.assertion.23\] .* assertion b\[j\]==1: Unknown$ -^\[main.assertion.24\] .* assertion a\[100\]==0: Unknown$ -^\[main.assertion.25\] .* assertion b\[1\]==0: Success$ -^\[main.assertion.26\] .* assertion ei\[0\]==1: Success$ -^\[main.assertion.27\] .* assertion ei\[0\]==0: Failure \(if reachable\)$ -^\[main.assertion.28\] .* assertion ei\[2\]==0: Success$ -^\[main.assertion.29\] .* assertion ei\[2\]==1: Failure \(if reachable\)$ -^\[main.assertion.30\] .* assertion ej\[0\]==0: Unknown$ -^\[main.assertion.31\] .* assertion ej\[2\]==0: Unknown$ -^\[main.assertion.32\] .* assertion ek\[0\]==0: Unknown$ +^\[main.assertion.1\] .* a\[1\]==0: Success$ +^\[main.assertion.2\] .* a\[1\]==1: Failure \(if reachable\)$ +^\[main.assertion.3\] .* b\[1\]==0: Success$ +^\[main.assertion.4\] .* b\[1\]==1: Failure \(if reachable\)$ +^\[main.assertion.5\] .* \*\(b\+1\)==0: Success$ +^\[main.assertion.6\] .* \*\(b\+1\)==1: Failure \(if reachable\)$ +^\[main.assertion.7\] .* \*\(1\+b\)==0: Unknown$ +^\[main.assertion.8\] .* \*\(1\+b\)==1: Unknown$ +^\[main.assertion.9\] .* 1\[b\]==0: Success$ +^\[main.assertion.10\] .* 1\[b\]==1: Failure \(if reachable\)$ +^\[main.assertion.11\] .* c\[0\]==0: Success$ +^\[main.assertion.12\] .* c\[0\]==1: Failure \(if reachable\)$ +^\[main.assertion.13\] .* d\[0\]==0: Unknown$ +^\[main.assertion.14\] .* d\[0\]==2: Unknown$ +^\[main.assertion.15\] .* d\[1\]==0: Success$ +^\[main.assertion.16\] .* a\[i\]==0: Success$ +^\[main.assertion.17\] .* a\[i\]==1: Failure \(if reachable\)$ +^\[main.assertion.18\] .* a\[j\]==0: Unknown$ +^\[main.assertion.19\] .* a\[j\]==1: Unknown$ +^\[main.assertion.20\] .* b\[i\]==1: Success$ +^\[main.assertion.21\] .* b\[i\]==0: Failure \(if reachable\)$ +^\[main.assertion.22\] .* b\[j\]==0: Unknown$ +^\[main.assertion.23\] .* b\[j\]==1: Unknown$ +^\[main.assertion.24\] .* a\[100\]==0: Unknown$ +^\[main.assertion.25\] .* b\[1\]==0: Success$ +^\[main.assertion.26\] .* ei\[0\]==1: Success$ +^\[main.assertion.27\] .* ei\[0\]==0: Failure \(if reachable\)$ +^\[main.assertion.28\] .* ei\[2\]==0: Success$ +^\[main.assertion.29\] .* ei\[2\]==1: Failure \(if reachable\)$ +^\[main.assertion.30\] .* ej\[0\]==0: Unknown$ +^\[main.assertion.31\] .* ej\[2\]==0: Unknown$ +^\[main.assertion.32\] .* ek\[0\]==0: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-char/test.desc b/regression/goto-analyzer/sensitivity-test-constants-char/test.desc index a74c6c89412..11129c480a6 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-char/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-char/test.desc @@ -3,7 +3,7 @@ sensitivity_test_constants_char.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x=='a': Success$ -^\[main.assertion.2\] .* assertion x=='b': Failure \(if reachable\)$ +^\[main.assertion.1\] .* x=='a': Success$ +^\[main.assertion.2\] .* x=='b': Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-float/test.desc b/regression/goto-analyzer/sensitivity-test-constants-float/test.desc index afa66b0ec00..0868c1da64c 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-float/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-float/test.desc @@ -3,7 +3,7 @@ sensitivity_test_constants_float.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x==0.0: Success$ -^\[main.assertion.2\] .* assertion x==1.0: Failure \(if reachable\)$ +^\[main.assertion.1\] .* x==0.0: Success$ +^\[main.assertion.2\] .* x==1.0: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-int/test.desc b/regression/goto-analyzer/sensitivity-test-constants-int/test.desc index 994707c59db..8a05deb8c53 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-int/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-int/test.desc @@ -3,33 +3,33 @@ sensitivity_test_constants_int.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x==0: Success$ -^\[main.assertion.2\] .* assertion x==1: Failure \(if reachable\)$ -^\[main.assertion.3\] .* assertion x==y: Unknown$ -^\[main.assertion.4\] .* assertion x<1: Success$ -^\[main.assertion.5\] .* assertion x<-1: Failure \(if reachable\)$ -^\[main.assertion.6\] .* assertion x-1: Success$ -^\[main.assertion.8\] .* assertion x>1: Failure \(if reachable\)$ -^\[main.assertion.9\] .* assertion x>y: Unknown$ -^\[main.assertion.10\] .* assertion x!=1: Success$ -^\[main.assertion.11\] .* assertion x!=0: Failure \(if reachable\)$ -^\[main.assertion.12\] .* assertion x!=y: Unknown$ -^\[main.assertion.13\] .* assertion !\(x==1\): Success$ -^\[main.assertion.14\] .* assertion !\(x==0\): Failure \(if reachable\)$ -^\[main.assertion.15\] .* assertion !\(x==y\): Unknown$ -^\[main.assertion.16\] .* assertion y<2: Unknown$ -^\[main.assertion.17\] .* assertion y>2: Unknown$ -^\[main.assertion.18\] .* assertion y==1: Unknown$ -^\[main.assertion.19\] .* assertion z==0: Success$ -^\[main.assertion.20\] .* assertion z==10: Failure \(if reachable\)$ -^\[main.assertion.21\] .* assertion x==0: Success \(unreachable\)$ -^\[main.assertion.22\] .* assertion x==1: Success \(unreachable\)$ -^\[main.assertion.23\] .* assertion y==0: Success \(unreachable\)$ -^\[main.assertion.24\] .* assertion a1==0: Unknown$ -^\[main.assertion.25\] .* assertion a2==0: Unknown$ -^\[main.assertion.26\] .* assertion a3==0: Unknown$ -^\[main.assertion.27\] .* assertion a4==0: Success$ -^\[main.assertion.28\] .* assertion a5==0: Success$ +^\[main.assertion.1\] .* x==0: Success$ +^\[main.assertion.2\] .* x==1: Failure \(if reachable\)$ +^\[main.assertion.3\] .* x==y: Unknown$ +^\[main.assertion.4\] .* x<1: Success$ +^\[main.assertion.5\] .* x<-1: Failure \(if reachable\)$ +^\[main.assertion.6\] .* x-1: Success$ +^\[main.assertion.8\] .* x>1: Failure \(if reachable\)$ +^\[main.assertion.9\] .* x>y: Unknown$ +^\[main.assertion.10\] .* x!=1: Success$ +^\[main.assertion.11\] .* x!=0: Failure \(if reachable\)$ +^\[main.assertion.12\] .* x!=y: Unknown$ +^\[main.assertion.13\] .* !\(x==1\): Success$ +^\[main.assertion.14\] .* !\(x==0\): Failure \(if reachable\)$ +^\[main.assertion.15\] .* !\(x==y\): Unknown$ +^\[main.assertion.16\] .* y<2: Unknown$ +^\[main.assertion.17\] .* y>2: Unknown$ +^\[main.assertion.18\] .* y==1: Unknown$ +^\[main.assertion.19\] .* z==0: Success$ +^\[main.assertion.20\] .* z==10: Failure \(if reachable\)$ +^\[main.assertion.21\] .* x==0: Success \(unreachable\)$ +^\[main.assertion.22\] .* x==1: Success \(unreachable\)$ +^\[main.assertion.23\] .* y==0: Success \(unreachable\)$ +^\[main.assertion.24\] .* a1==0: Unknown$ +^\[main.assertion.25\] .* a2==0: Unknown$ +^\[main.assertion.26\] .* a3==0: Unknown$ +^\[main.assertion.27\] .* a4==0: Success$ +^\[main.assertion.28\] .* a5==0: Success$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc index 12cd47f791f..62ff39b5230 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc @@ -3,27 +3,27 @@ sensitivity_test_constants_pointer_to_constants_array.c --variable --pointers --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion p==&a\[0\]: Success$ -^\[main.assertion.2\] .* assertion \*p==1: Success$ -^\[main\.assertion\.3\] .* assertion p\[1\]==2: Unknown$ -^\[main\.assertion\.4\] .* assertion 1\[p\]==2: Unknown$ -^\[main\.assertion\.5\] .* assertion \*\(p\+1\)==2: Unknown$ -^\[main\.assertion\.6\] .* assertion \*\(1\+p\)==2: Unknown$ -^\[main\.assertion\.7\] .* assertion \*\(p-1\)==1: Unknown$ -^\[main\.assertion\.8\] .* assertion q==p\+1: Unknown$ -^\[main\.assertion\.9\] .* assertion \*q==2: Unknown$ -^\[main\.assertion\.10\] .* assertion q-p==x: Unknown$ -^\[main\.assertion\.11\] .* assertion a\[1\]==4: Unknown$ -^\[main\.assertion\.12\] .* assertion a\[1\]==5: Unknown$ -^\[main\.assertion\.13\] .* assertion a\[1\]==6: Unknown$ -^\[main\.assertion\.14\] .* assertion a\[1\]==7: Unknown$ -^\[main\.assertion\.15\] .* assertion \*r==2: Unknown$ -^\[main\.assertion\.16\] .* assertion \*r==1: Unknown$ -^\[main\.assertion\.17\] .* assertion \*s==0: Unknown$ -^\[main\.assertion\.18\] .* assertion \*s==1: Unknown$ -^\[main\.assertion\.19\] .* assertion t==p\+i: Unknown$ -^\[main\.assertion\.20\] .* assertion t-p==y: Unknown$ -^\[main\.assertion\.21\] .* assertion a\[i\]==5: Unknown$ -^\[main\.assertion\.22\] .* assertion a\[1\]==5: Unknown$ +^\[main.assertion.1\] .* p==&a\[0\]: Success$ +^\[main.assertion.2\] .* \*p==1: Success$ +^\[main\.assertion\.3\] .* p\[1\]==2: Unknown$ +^\[main\.assertion\.4\] .* 1\[p\]==2: Unknown$ +^\[main\.assertion\.5\] .* \*\(p\+1\)==2: Unknown$ +^\[main\.assertion\.6\] .* \*\(1\+p\)==2: Unknown$ +^\[main\.assertion\.7\] .* \*\(p-1\)==1: Unknown$ +^\[main\.assertion\.8\] .* q==p\+1: Unknown$ +^\[main\.assertion\.9\] .* \*q==2: Unknown$ +^\[main\.assertion\.10\] .* q-p==x: Unknown$ +^\[main\.assertion\.11\] .* a\[1\]==4: Unknown$ +^\[main\.assertion\.12\] .* a\[1\]==5: Unknown$ +^\[main\.assertion\.13\] .* a\[1\]==6: Unknown$ +^\[main\.assertion\.14\] .* a\[1\]==7: Unknown$ +^\[main\.assertion\.15\] .* \*r==2: Unknown$ +^\[main\.assertion\.16\] .* \*r==1: Unknown$ +^\[main\.assertion\.17\] .* \*s==0: Unknown$ +^\[main\.assertion\.18\] .* \*s==1: Unknown$ +^\[main\.assertion\.19\] .* t==p\+i: Unknown$ +^\[main\.assertion\.20\] .* t-p==y: Unknown$ +^\[main\.assertion\.21\] .* a\[i\]==5: Unknown$ +^\[main\.assertion\.22\] .* a\[1\]==5: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/test.desc index 0a001aa5642..d4d18683447 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/test.desc @@ -3,11 +3,11 @@ sensitivity_test_constants_pointer_to_constants_pointer.c --variable --pointers --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion \*\*x==0: Success$ -^\[main.assertion.2\] .* assertion \*\*x==1: Failure \(if reachable\)$ -^\[main.assertion.3\] .* assertion \*\*x==1: Success$ -^\[main.assertion.4\] .* assertion \*\*x==0: Failure \(if reachable\)$ -^\[main.assertion.5\] .* assertion a==2: Success$ -^\[main.assertion.6\] .* assertion a==1: Failure \(if reachable\)$ +^\[main.assertion.1\] .* \*\*x==0: Success$ +^\[main.assertion.2\] .* \*\*x==1: Failure \(if reachable\)$ +^\[main.assertion.3\] .* \*\*x==1: Success$ +^\[main.assertion.4\] .* \*\*x==0: Failure \(if reachable\)$ +^\[main.assertion.5\] .* a==2: Success$ +^\[main.assertion.6\] .* a==1: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-struct/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-struct/test.desc index c7abd5e6821..f6e0a55e3ef 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-struct/test.desc @@ -3,12 +3,12 @@ sensitivity_test_constants_pointer_to_constants_struct.c --variable --pointers --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion \(\*p\).a==0: Success$ -^\[main.assertion.2\] .* assertion \(\*p\).a==1: Failure \(if reachable\)$ -^\[main.assertion.3\] .* assertion p->a==0: Success$ -^\[main.assertion.4\] .* assertion p->a==1: Failure \(if reachable\)$ -^\[main.assertion.5\] .* assertion p->b==2.0: Success$ -^\[main.assertion.6\] .* assertion p->b==1.0: Failure \(if reachable\)$ +^\[main.assertion.1\] .* \(\*p\).a==0: Success$ +^\[main.assertion.2\] .* \(\*p\).a==1: Failure \(if reachable\)$ +^\[main.assertion.3\] .* p->a==0: Success$ +^\[main.assertion.4\] .* p->a==1: Failure \(if reachable\)$ +^\[main.assertion.5\] .* p->b==2.0: Success$ +^\[main.assertion.6\] .* p->b==1.0: Failure \(if reachable\)$ -- ^warning: ignoring -- diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc index 4758432cea8..56d38be4bb0 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc @@ -3,27 +3,27 @@ sensitivity_test_constants_pointer_to_two_value_array.c --variable --pointers --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion p==&a\[0\]: Success$ -^\[main.assertion.2\] .* assertion \*p==1: Unknown$ -^\[main\.assertion\.3\] .* assertion p\[1\]==2: Unknown$ -^\[main\.assertion\.4\] .* assertion 1\[p\]==2: Unknown$ -^\[main\.assertion\.5\] .* assertion \*\(p\+1\)==2: Unknown$ -^\[main\.assertion\.6\] .* assertion \*\(1\+p\)==2: Unknown$ -^\[main\.assertion\.7\] .* assertion \*\(p-1\)==1: Unknown$ -^\[main.assertion.8\] .* assertion q==p\+1: Unknown$ -^\[main.assertion.9\] .* assertion \*q==2: Unknown$ -^\[main.assertion.10\] .* assertion q-p==x: Unknown$ -^\[main.assertion.11\] .* assertion a\[1\]==4: Unknown$ -^\[main.assertion.12\] .* assertion a\[1\]==5: Unknown$ -^\[main\.assertion\.13\] .* assertion a\[1\]==6: Unknown$ -^\[main\.assertion\.14\] .* assertion a\[1\]==7: Unknown$ -^\[main.assertion.15\] .* assertion \*r==2: Unknown$ -^\[main.assertion.16\] .* assertion \*r==1: Unknown$ -^\[main.assertion.17\] .* assertion \*s==0: Unknown$ -^\[main.assertion.18\] .* assertion \*s==1: Unknown$ -^\[main.assertion.19\] .* assertion t==p\+i: Unknown$ -^\[main.assertion.20\] .* assertion t-p==y: Unknown$ -^\[main.assertion.21\] .* assertion a\[i\]==5: Unknown$ -^\[main.assertion.22\] .* assertion a\[1\]==5: Unknown$ +^\[main.assertion.1\] .* p==&a\[0\]: Success$ +^\[main.assertion.2\] .* \*p==1: Unknown$ +^\[main\.assertion\.3\] .* p\[1\]==2: Unknown$ +^\[main\.assertion\.4\] .* 1\[p\]==2: Unknown$ +^\[main\.assertion\.5\] .* \*\(p\+1\)==2: Unknown$ +^\[main\.assertion\.6\] .* \*\(1\+p\)==2: Unknown$ +^\[main\.assertion\.7\] .* \*\(p-1\)==1: Unknown$ +^\[main.assertion.8\] .* q==p\+1: Unknown$ +^\[main.assertion.9\] .* \*q==2: Unknown$ +^\[main.assertion.10\] .* q-p==x: Unknown$ +^\[main.assertion.11\] .* a\[1\]==4: Unknown$ +^\[main.assertion.12\] .* a\[1\]==5: Unknown$ +^\[main\.assertion\.13\] .* a\[1\]==6: Unknown$ +^\[main\.assertion\.14\] .* a\[1\]==7: Unknown$ +^\[main.assertion.15\] .* \*r==2: Unknown$ +^\[main.assertion.16\] .* \*r==1: Unknown$ +^\[main.assertion.17\] .* \*s==0: Unknown$ +^\[main.assertion.18\] .* \*s==1: Unknown$ +^\[main.assertion.19\] .* t==p\+i: Unknown$ +^\[main.assertion.20\] .* t-p==y: Unknown$ +^\[main.assertion.21\] .* a\[i\]==5: Unknown$ +^\[main.assertion.22\] .* a\[1\]==5: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/test.desc index 908eee17958..225a8c942df 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/test.desc @@ -3,11 +3,11 @@ sensitivity_test_constants_pointer_to_two_value_struct.c --variable --pointers --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion \(\*p\).a==0: Unknown$ -^\[main.assertion.2\] .* assertion \(\*p\).a==1: Unknown$ -^\[main.assertion.3\] .* assertion p->a==0: Unknown$ -^\[main.assertion.4\] .* assertion p->a==1: Unknown$ -^\[main.assertion.5\] .* assertion p->b==2.0: Unknown$ -^\[main.assertion.6\] .* assertion p->b==1.0: Unknown$ +^\[main.assertion.1\] .* \(\*p\).a==0: Unknown$ +^\[main.assertion.2\] .* \(\*p\).a==1: Unknown$ +^\[main.assertion.3\] .* p->a==0: Unknown$ +^\[main.assertion.4\] .* p->a==1: Unknown$ +^\[main.assertion.5\] .* p->b==2.0: Unknown$ +^\[main.assertion.6\] .* p->b==1.0: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc index 657e621a90f..a9800cb3943 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc @@ -3,19 +3,19 @@ sensitivity_test_constants_pointer.c --variable --pointers --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x==&a: Success$ -^\[main.assertion.2\] .* assertion x==&b: Failure \(if reachable\)$ -^\[main.assertion.3\] .* assertion x==x2: Success$ -^\[main.assertion.4\] .* assertion x==y: Failure \(if reachable\)$ -^\[main.assertion.5\] .* assertion \*x==0: Success$ -^\[main.assertion.6\] .* assertion \*x==1: Failure \(if reachable\)$ -^\[main.assertion.7\] .* assertion \*x==1: Success$ -^\[main.assertion.8\] .* assertion \*x==0: Failure \(if reachable\)$ -^\[main.assertion.9\] .* assertion a==2: Success$ -^\[main.assertion.10\] .* assertion a==0: Failure \(if reachable\)$ -^\[main.assertion.11\] .* assertion x==&a: Success$ -^\[main.assertion.12\] .* assertion \*x==0: Unknown$ -^\[main.assertion.13\] .* assertion x==&a: Unknown$ -^\[main.assertion.14\] .* assertion x==&b: Unknown$ +^\[main.assertion.1\] .* x==&a: Success$ +^\[main.assertion.2\] .* x==&b: Failure \(if reachable\)$ +^\[main.assertion.3\] .* x==x2: Success$ +^\[main.assertion.4\] .* x==y: Failure \(if reachable\)$ +^\[main.assertion.5\] .* \*x==0: Success$ +^\[main.assertion.6\] .* \*x==1: Failure \(if reachable\)$ +^\[main.assertion.7\] .* \*x==1: Success$ +^\[main.assertion.8\] .* \*x==0: Failure \(if reachable\)$ +^\[main.assertion.9\] .* a==2: Success$ +^\[main.assertion.10\] .* a==0: Failure \(if reachable\)$ +^\[main.assertion.11\] .* x==&a: Success$ +^\[main.assertion.12\] .* \*x==0: Unknown$ +^\[main.assertion.13\] .* x==&a: Unknown$ +^\[main.assertion.14\] .* x==&b: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/test.desc index 1fd0ef53aec..29eb717e225 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/test.desc @@ -3,22 +3,22 @@ sensitivity_test_constants_struct_of_constants_array.c --variable --structs --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x.a\[0\]==0: Success$ -^\[main.assertion.2\] .* assertion \*\(x.a\+0\)==0: Success$ -^\[main.assertion.3\] .* assertion \*\(0\+x.a\)==0: Success$ -^\[main.assertion.4\] .* assertion 0\[x.a\]==0: Success$ -^\[main.assertion.5\] .* assertion x.a\[0\]==0: Success$ -^\[main.assertion.6\] .* assertion x.a\[1\]==1: Success$ -^\[main.assertion.7\] .* assertion x.b\[0\]==3.0f: Success$ -^\[main.assertion.8\] .* assertion x.a\[0\]==0: Success$ -^\[main.assertion.9\] .* assertion x.a\[1\]==1: Success$ -^\[main.assertion.10\] .* assertion x.b\[2\]>0.0f: Unknown$ -^\[main.assertion.11\] .* assertion x.b\[2\]==15.0f: Unknown$ -^\[main.assertion.12\] .* assertion x.b\[2\]==1.0f: Unknown$ -^\[main.assertion.13\] .* assertion x.b\[0\]==3.0f: Success$ -^\[main.assertion.14\] .* assertion x.a\[0\]<12: Unknown$ -^\[main.assertion.15\] .* assertion x.a\[0\]>2: Unknown$ -^\[main.assertion.16\] .* assertion x.a\[0\]==0: Unknown$ -^\[main.assertion.17\] .* assertion x.a\[1\]==1: Success$ +^\[main.assertion.1\] .* x.a\[0\]==0: Success$ +^\[main.assertion.2\] .* \*\(x.a\+0\)==0: Success$ +^\[main.assertion.3\] .* \*\(0\+x.a\)==0: Success$ +^\[main.assertion.4\] .* 0\[x.a\]==0: Success$ +^\[main.assertion.5\] .* x.a\[0\]==0: Success$ +^\[main.assertion.6\] .* x.a\[1\]==1: Success$ +^\[main.assertion.7\] .* x.b\[0\]==3.0f: Success$ +^\[main.assertion.8\] .* x.a\[0\]==0: Success$ +^\[main.assertion.9\] .* x.a\[1\]==1: Success$ +^\[main.assertion.10\] .* x.b\[2\]>0.0f: Unknown$ +^\[main.assertion.11\] .* x.b\[2\]==15.0f: Unknown$ +^\[main.assertion.12\] .* x.b\[2\]==1.0f: Unknown$ +^\[main.assertion.13\] .* x.b\[0\]==3.0f: Success$ +^\[main.assertion.14\] .* x.a\[0\]<12: Unknown$ +^\[main.assertion.15\] .* x.a\[0\]>2: Unknown$ +^\[main.assertion.16\] .* x.a\[0\]==0: Unknown$ +^\[main.assertion.17\] .* x.a\[1\]==1: Success$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/test.desc index 81727577440..78664b1ea0d 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/test.desc @@ -3,31 +3,31 @@ sensitivity_test_constants_struct_of_constants_pointer.c --variable --structs --pointers --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x.a==&a1: Success$ -^\[main.assertion.2\] .* assertion x.a==&a2: Failure \(if reachable\)$ -^\[main.assertion.3\] .* assertion x.b==&b1: Success$ -^\[main.assertion.4\] .* assertion x.b==&b2: Failure \(if reachable\)$ -^\[main.assertion.5\] .* assertion \*x.a==0: Success$ -^\[main.assertion.6\] .* assertion \*x.a==100: Failure \(if reachable\)$ -^\[main.assertion.7\] .* assertion \*x.b==10.0f: Success$ -^\[main.assertion.8\] .* assertion \*x.b==110.0f: Failure \(if reachable\)$ -^\[main.assertion.9\] .* assertion x.a==&a1: Success$ -^\[main.assertion.10\] .* assertion x.a==&a2: Failure \(if reachable\)$ -^\[main.assertion.11\] .* assertion \*x.a==0: Success$ -^\[main.assertion.12\] .* assertion \*x.a==100: Failure \(if reachable\)$ -^\[main.assertion.13\] .* assertion x.a==&a1: Success$ -^\[main.assertion.14\] .* assertion x.b==&b2: Unknown$ -^\[main.assertion.15\] .* assertion x.b==&b3: Unknown$ -^\[main.assertion.16\] .* assertion \*x.a==0: Success$ -^\[main.assertion.17\] .* assertion \*x.b==11.0f: Unknown$ -^\[main.assertion.18\] .* assertion \*x.b==12.0f: Unknown$ -^\[main.assertion.19\] .* assertion x.a==&a2: Unknown$ -^\[main.assertion.20\] .* assertion x.a==&a3: Unknown$ -^\[main.assertion.21\] .* assertion x.b==&b3: Unknown$ -^\[main.assertion.22\] .* assertion x.b==&b4: Unknown$ -^\[main.assertion.23\] .* assertion \*x.a==1: Unknown$ -^\[main.assertion.24\] .* assertion \*x.a==2: Unknown$ -^\[main.assertion.25\] .* assertion \*x.b==12.0f: Unknown$ -^\[main.assertion.26\] .* assertion \*x.b==13.0f: Unknown$ +^\[main.assertion.1\] .* x.a==&a1: Success$ +^\[main.assertion.2\] .* x.a==&a2: Failure \(if reachable\)$ +^\[main.assertion.3\] .* x.b==&b1: Success$ +^\[main.assertion.4\] .* x.b==&b2: Failure \(if reachable\)$ +^\[main.assertion.5\] .* \*x.a==0: Success$ +^\[main.assertion.6\] .* \*x.a==100: Failure \(if reachable\)$ +^\[main.assertion.7\] .* \*x.b==10.0f: Success$ +^\[main.assertion.8\] .* \*x.b==110.0f: Failure \(if reachable\)$ +^\[main.assertion.9\] .* x.a==&a1: Success$ +^\[main.assertion.10\] .* x.a==&a2: Failure \(if reachable\)$ +^\[main.assertion.11\] .* \*x.a==0: Success$ +^\[main.assertion.12\] .* \*x.a==100: Failure \(if reachable\)$ +^\[main.assertion.13\] .* x.a==&a1: Success$ +^\[main.assertion.14\] .* x.b==&b2: Unknown$ +^\[main.assertion.15\] .* x.b==&b3: Unknown$ +^\[main.assertion.16\] .* \*x.a==0: Success$ +^\[main.assertion.17\] .* \*x.b==11.0f: Unknown$ +^\[main.assertion.18\] .* \*x.b==12.0f: Unknown$ +^\[main.assertion.19\] .* x.a==&a2: Unknown$ +^\[main.assertion.20\] .* x.a==&a3: Unknown$ +^\[main.assertion.21\] .* x.b==&b3: Unknown$ +^\[main.assertion.22\] .* x.b==&b4: Unknown$ +^\[main.assertion.23\] .* \*x.a==1: Unknown$ +^\[main.assertion.24\] .* \*x.a==2: Unknown$ +^\[main.assertion.25\] .* \*x.b==12.0f: Unknown$ +^\[main.assertion.26\] .* \*x.b==13.0f: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/test.desc index 4420e433c06..a479614cb9a 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/test.desc @@ -3,16 +3,16 @@ sensitivity_test_constants_struct_of_constants_struct.c --variable --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x.s1.a==0: Success$ -^\[main.assertion.2\] .* assertion x.s2.b==3.0f: Success$ -^\[main.assertion.3\] .* assertion x.s1.a==0: Success$ -^\[main.assertion.4\] .* assertion x.s1.a==10: Failure \(if reachable\)$ -^\[main.assertion.5\] .* assertion x.s1.b==1.0f: Success$ -^\[main.assertion.6\] .* assertion x.s2.b==3.0f: Unknown$ -^\[main.assertion.7\] .* assertion x.s2.b==0.0f: Unknown$ -^\[main.assertion.8\] .* assertion x.s1.a==20: Unknown$ -^\[main.assertion.9\] .* assertion x.s1.a<30: Unknown$ -^\[main.assertion.10\] .* assertion x.s2.a==22: Unknown$ -^\[main.assertion.11\] .* assertion x.s2.a<30: Unknown$ +^\[main.assertion.1\] .* x.s1.a==0: Success$ +^\[main.assertion.2\] .* x.s2.b==3.0f: Success$ +^\[main.assertion.3\] .* x.s1.a==0: Success$ +^\[main.assertion.4\] .* x.s1.a==10: Failure \(if reachable\)$ +^\[main.assertion.5\] .* x.s1.b==1.0f: Success$ +^\[main.assertion.6\] .* x.s2.b==3.0f: Unknown$ +^\[main.assertion.7\] .* x.s2.b==0.0f: Unknown$ +^\[main.assertion.8\] .* x.s1.a==20: Unknown$ +^\[main.assertion.9\] .* x.s1.a<30: Unknown$ +^\[main.assertion.10\] .* x.s2.a==22: Unknown$ +^\[main.assertion.11\] .* x.s2.a<30: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/test.desc index 3dd5505c955..8f7111b0fcf 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/test.desc @@ -3,22 +3,22 @@ sensitivity_test_constants_struct_of_two_value_array.c --variable --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x.a\[0\]==0: Unknown$ -^\[main.assertion.2\] .* assertion \*\(x.a\+0\)==0: Unknown$ -^\[main.assertion.3\] .* assertion \*\(0\+x.a\)==0: Unknown$ -^\[main.assertion.4\] .* assertion 0\[x.a\]==0: Unknown$ -^\[main.assertion.5\] .* assertion x.a\[0\]==0: Unknown$ -^\[main.assertion.6\] .* assertion x.a\[1\]==1: Unknown$ -^\[main.assertion.7\] .* assertion x.b\[0\]==3.0f: Unknown$ -^\[main.assertion.8\] .* assertion x.a\[0\]==0: Unknown$ -^\[main.assertion.9\] .* assertion x.a\[1\]==1: Unknown$ -^\[main.assertion.10\] .* assertion x.b\[2\]>0.0f: Unknown$ -^\[main.assertion.11\] .* assertion x.b\[2\]==15.0f: Unknown$ -^\[main.assertion.12\] .* assertion x.b\[2\]==1.0f: Unknown$ -^\[main.assertion.13\] .* assertion x.b\[0\]==3.0f: Unknown$ -^\[main.assertion.14\] .* assertion x.a\[0\]<12: Unknown$ -^\[main.assertion.15\] .* assertion x.a\[0\]>2: Unknown$ -^\[main.assertion.16\] .* assertion x.a\[0\]==0: Unknown$ -^\[main.assertion.17\] .* assertion x.a\[1\]==1: Unknown$ +^\[main.assertion.1\] .* x.a\[0\]==0: Unknown$ +^\[main.assertion.2\] .* \*\(x.a\+0\)==0: Unknown$ +^\[main.assertion.3\] .* \*\(0\+x.a\)==0: Unknown$ +^\[main.assertion.4\] .* 0\[x.a\]==0: Unknown$ +^\[main.assertion.5\] .* x.a\[0\]==0: Unknown$ +^\[main.assertion.6\] .* x.a\[1\]==1: Unknown$ +^\[main.assertion.7\] .* x.b\[0\]==3.0f: Unknown$ +^\[main.assertion.8\] .* x.a\[0\]==0: Unknown$ +^\[main.assertion.9\] .* x.a\[1\]==1: Unknown$ +^\[main.assertion.10\] .* x.b\[2\]>0.0f: Unknown$ +^\[main.assertion.11\] .* x.b\[2\]==15.0f: Unknown$ +^\[main.assertion.12\] .* x.b\[2\]==1.0f: Unknown$ +^\[main.assertion.13\] .* x.b\[0\]==3.0f: Unknown$ +^\[main.assertion.14\] .* x.a\[0\]<12: Unknown$ +^\[main.assertion.15\] .* x.a\[0\]>2: Unknown$ +^\[main.assertion.16\] .* x.a\[0\]==0: Unknown$ +^\[main.assertion.17\] .* x.a\[1\]==1: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/test.desc index 5249580ade1..955f2504d87 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/test.desc @@ -3,31 +3,31 @@ sensitivity_test_constants_struct_of_two_value_pointer.c --variable --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x.a==&a1: Unknown$ -^\[main.assertion.2\] .* assertion x.a==&a2: Unknown$ -^\[main.assertion.3\] .* assertion x.b==&b1: Unknown$ -^\[main.assertion.4\] .* assertion x.b==&b2: Unknown$ -^\[main.assertion.5\] .* assertion \*x.a==0: Unknown$ -^\[main.assertion.6\] .* assertion \*x.a==100: Unknown$ -^\[main.assertion.7\] .* assertion \*x.b==10.0f: Unknown$ -^\[main.assertion.8\] .* assertion \*x.b==110.0f: Unknown$ -^\[main.assertion.9\] .* assertion x.a==&a1: Unknown$ -^\[main.assertion.10\] .* assertion x.a==&a2: Unknown$ -^\[main.assertion.11\] .* assertion \*x.a==0: Unknown$ -^\[main.assertion.12\] .* assertion \*x.a==100: Unknown$ -^\[main.assertion.13\] .* assertion x.a==&a1: Unknown$ -^\[main.assertion.14\] .* assertion x.b==&b2: Unknown$ -^\[main.assertion.15\] .* assertion x.b==&b3: Unknown$ -^\[main.assertion.16\] .* assertion \*x.a==0: Unknown$ -^\[main.assertion.17\] .* assertion \*x.b==11.0f: Unknown$ -^\[main.assertion.18\] .* assertion \*x.b==12.0f: Unknown$ -^\[main.assertion.19\] .* assertion x.a==&a2: Unknown$ -^\[main.assertion.20\] .* assertion x.a==&a3: Unknown$ -^\[main.assertion.21\] .* assertion x.b==&b3: Unknown$ -^\[main.assertion.22\] .* assertion x.b==&b4: Unknown$ -^\[main.assertion.23\] .* assertion \*x.a==1: Unknown$ -^\[main.assertion.24\] .* assertion \*x.a==2: Unknown$ -^\[main.assertion.25\] .* assertion \*x.b==12.0f: Unknown$ -^\[main.assertion.26\] .* assertion \*x.b==13.0f: Unknown$ +^\[main.assertion.1\] .* x.a==&a1: Unknown$ +^\[main.assertion.2\] .* x.a==&a2: Unknown$ +^\[main.assertion.3\] .* x.b==&b1: Unknown$ +^\[main.assertion.4\] .* x.b==&b2: Unknown$ +^\[main.assertion.5\] .* \*x.a==0: Unknown$ +^\[main.assertion.6\] .* \*x.a==100: Unknown$ +^\[main.assertion.7\] .* \*x.b==10.0f: Unknown$ +^\[main.assertion.8\] .* \*x.b==110.0f: Unknown$ +^\[main.assertion.9\] .* x.a==&a1: Unknown$ +^\[main.assertion.10\] .* x.a==&a2: Unknown$ +^\[main.assertion.11\] .* \*x.a==0: Unknown$ +^\[main.assertion.12\] .* \*x.a==100: Unknown$ +^\[main.assertion.13\] .* x.a==&a1: Unknown$ +^\[main.assertion.14\] .* x.b==&b2: Unknown$ +^\[main.assertion.15\] .* x.b==&b3: Unknown$ +^\[main.assertion.16\] .* \*x.a==0: Unknown$ +^\[main.assertion.17\] .* \*x.b==11.0f: Unknown$ +^\[main.assertion.18\] .* \*x.b==12.0f: Unknown$ +^\[main.assertion.19\] .* x.a==&a2: Unknown$ +^\[main.assertion.20\] .* x.a==&a3: Unknown$ +^\[main.assertion.21\] .* x.b==&b3: Unknown$ +^\[main.assertion.22\] .* x.b==&b4: Unknown$ +^\[main.assertion.23\] .* \*x.a==1: Unknown$ +^\[main.assertion.24\] .* \*x.a==2: Unknown$ +^\[main.assertion.25\] .* \*x.b==12.0f: Unknown$ +^\[main.assertion.26\] .* \*x.b==13.0f: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc index bdf9535e008..93b3589bc9a 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc @@ -3,14 +3,14 @@ sensitivity_test_constants_struct.c --variable --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x.a==0: Success$ -^\[main.assertion.2\] .* assertion x.a==1: Failure \(if reachable\)$ -^\[main.assertion.3\] .* assertion x.a==0: Success$ -^\[main.assertion.4\] .* assertion x.a==0: Success$ -^\[main.assertion.5\] .* assertion x.b>0.0f: Unknown$ -^\[main.assertion.6\] .* assertion x.b==1.0f: Unknown$ -^\[main.assertion.7\] .* assertion x.a<2: Unknown$ -^\[main.assertion.8\] .* assertion x.a>2: Unknown$ -^\[main.assertion.9\] .* assertion x.a==1: Unknown$ +^\[main.assertion.1\] .* x.a==0: Success$ +^\[main.assertion.2\] .* x.a==1: Failure \(if reachable\)$ +^\[main.assertion.3\] .* x.a==0: Success$ +^\[main.assertion.4\] .* x.a==0: Success$ +^\[main.assertion.5\] .* x.b>0.0f: Unknown$ +^\[main.assertion.6\] .* x.b==1.0f: Unknown$ +^\[main.assertion.7\] .* x.a<2: Unknown$ +^\[main.assertion.8\] .* x.a>2: Unknown$ +^\[main.assertion.9\] .* x.a==1: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/test.desc index 953508ea2a3..fc61fe8bbfa 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/test.desc @@ -3,71 +3,71 @@ sensitivity_test_two_value_array_of_two_value_array.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion a\[1\]\[2\]==0: Unknown$ -^\[main.assertion.2\] .* assertion a\[1\]\[2\]==1: Unknown$ -^\[main.assertion.3\] .* assertion b\[1\]\[2\]==5: Unknown$ -^\[main.assertion.4\] .* assertion b\[1\]\[2\]==0: Unknown$ -^\[main.assertion.5\] .* assertion \*\(b\[1\]\+2\)==5: Unknown$ -^\[main.assertion.6\] .* assertion \*\(b\[1\]\+2\)==0: Unknown$ -^\[main.assertion.7\] .* assertion \(\*\(b\+1\)\)\[2\]==5: Unknown$ -^\[main.assertion.8\] .* assertion \(\*\(b\+1\)\)\[2\]==0: Unknown$ -^\[main.assertion.9\] .* assertion \*\(\*\(b\+1\)\+2\)==5: Unknown$ -^\[main.assertion.10\] .* assertion \*\(\*\(b\+1\)\+2\)==0: Unknown$ -^\[main.assertion.11\] .* assertion 1\[b\]\[2\]==5: Unknown$ -^\[main.assertion.12\] .* assertion 1\[b\]\[2\]==0: Unknown$ -^\[main.assertion.13\] .* assertion \*\(1\[b\]\+2\)==5: Unknown$ -^\[main.assertion.14\] .* assertion \*\(1\[b\]\+2\)==0: Unknown$ -^\[main.assertion.15\] .* assertion \(\*\(1\+b\)\)\[2\]==5: Unknown$ -^\[main.assertion.16\] .* assertion \(\*\(1\+b\)\)\[2\]==0: Unknown$ -^\[main.assertion.17\] .* assertion \*\(\*\(1\+b\)\+2\)==5: Unknown$ -^\[main.assertion.18\] .* assertion \*\(\*\(1\+b\)\+2\)==0: Unknown$ -^\[main.assertion.19\] .* assertion 2\[1\[b\]\]==5: Unknown$ -^\[main.assertion.20\] .* assertion 2\[1\[b\]\]==0: Unknown$ -^\[main.assertion.21\] .* assertion \*\(2\+1\[b\]\)==5: Unknown$ -^\[main.assertion.22\] .* assertion \*\(2\+1\[b\]\)==0: Unknown$ -^\[main.assertion.23\] .* assertion \*\(2\+\*\(1\+b\)\)==5: Unknown$ -^\[main.assertion.24\] .* assertion \*\(2\+\*\(1\+b\)\)==0: Unknown$ -^\[main.assertion.25\] .* assertion a\[0\]\[1\]==0: Unknown$ -^\[main.assertion.26\] .* assertion a\[0\]\[1\]==1: Unknown$ -^\[main.assertion.27\] .* assertion a\[0\]\[2\]==0: Unknown$ -^\[main.assertion.28\] .* assertion b\[0\]\[1\]==2: Unknown$ -^\[main.assertion.29\] .* assertion b\[0\]\[1\]==3: Unknown$ -^\[main.assertion.30\] .* assertion b\[0\]\[2\]==2: Unknown$ -^\[main.assertion.31\] .* assertion a\[i\]\[1\]==0: Unknown$ -^\[main.assertion.32\] .* assertion a\[i\]\[1\]==1: Unknown$ -^\[main.assertion.33\] .* assertion a\[1\]\[i\]==0: Unknown$ -^\[main.assertion.34\] .* assertion a\[1\]\[i\]==1: Unknown$ -^\[main.assertion.35\] .* assertion a\[i\]\[i\]==0: Unknown$ -^\[main.assertion.36\] .* assertion a\[i\]\[i\]==1: Unknown$ -^\[main.assertion.37\] .* assertion a\[j\]\[1\]==0: Unknown$ -^\[main.assertion.38\] .* assertion a\[j\]\[1\]==1: Unknown$ -^\[main.assertion.39\] .* assertion a\[1\]\[j\]==0: Unknown$ -^\[main.assertion.40\] .* assertion a\[1\]\[j\]==1: Unknown$ -^\[main.assertion.41\] .* assertion a\[j\]\[j\]==0: Unknown$ -^\[main.assertion.42\] .* assertion a\[j\]\[j\]==1: Unknown$ -^\[main.assertion.43\] .* assertion b\[i\]\[1\]==1: Unknown$ -^\[main.assertion.44\] .* assertion b\[i\]\[1\]==11: Unknown$ -^\[main.assertion.45\] .* assertion b\[1\]\[i\]==3: Unknown$ -^\[main.assertion.46\] .* assertion b\[1\]\[i\]==11: Unknown$ -^\[main.assertion.47\] .* assertion b\[i\]\[i\]==0: Unknown$ -^\[main.assertion.48\] .* assertion b\[i\]\[i\]==11: Unknown$ -^\[main.assertion.49\] .* assertion b\[j\]\[1\]==1: Unknown$ -^\[main.assertion.50\] .* assertion b\[j\]\[1\]==11: Unknown$ -^\[main.assertion.51\] .* assertion b\[1\]\[j\]==3: Unknown$ -^\[main.assertion.52\] .* assertion b\[1\]\[j\]==11: Unknown$ -^\[main.assertion.53\] .* assertion b\[j\]\[j\]==0: Unknown$ -^\[main.assertion.54\] .* assertion b\[j\]\[j\]==11: Unknown$ -^\[main.assertion.55\] .* assertion a\[100\]\[0\]==0: Unknown$ -^\[main.assertion.56\] .* assertion a\[0\]\[100\]==0: Unknown$ -^\[main.assertion.57\] .* assertion c==0: Success$ -^\[main.assertion.58\] .* assertion c==0: Success$ -^\[main.assertion.59\] .* assertion ei\[0\]\[1\]==1: Unknown$ -^\[main.assertion.60\] .* assertion ei\[0\]\[1\]==0: Unknown$ -^\[main.assertion.61\] .* assertion ei\[2\]\[1\]==0: Unknown$ -^\[main.assertion.62\] .* assertion ei\[2\]\[1\]==1: Unknown$ -^\[main.assertion.63\] .* assertion ej\[0\]\[1\]==0: Unknown$ -^\[main.assertion.64\] .* assertion ej\[2\]\[1\]==0: Unknown$ -^\[main.assertion.65\] .* assertion ek\[0\]\[1\]==0: Unknown$ -^\[main.assertion.66\] .* assertion c==0: Success$ +^\[main.assertion.1\] .* a\[1\]\[2\]==0: Unknown$ +^\[main.assertion.2\] .* a\[1\]\[2\]==1: Unknown$ +^\[main.assertion.3\] .* b\[1\]\[2\]==5: Unknown$ +^\[main.assertion.4\] .* b\[1\]\[2\]==0: Unknown$ +^\[main.assertion.5\] .* \*\(b\[1\]\+2\)==5: Unknown$ +^\[main.assertion.6\] .* \*\(b\[1\]\+2\)==0: Unknown$ +^\[main.assertion.7\] .* \(\*\(b\+1\)\)\[2\]==5: Unknown$ +^\[main.assertion.8\] .* \(\*\(b\+1\)\)\[2\]==0: Unknown$ +^\[main.assertion.9\] .* \*\(\*\(b\+1\)\+2\)==5: Unknown$ +^\[main.assertion.10\] .* \*\(\*\(b\+1\)\+2\)==0: Unknown$ +^\[main.assertion.11\] .* 1\[b\]\[2\]==5: Unknown$ +^\[main.assertion.12\] .* 1\[b\]\[2\]==0: Unknown$ +^\[main.assertion.13\] .* \*\(1\[b\]\+2\)==5: Unknown$ +^\[main.assertion.14\] .* \*\(1\[b\]\+2\)==0: Unknown$ +^\[main.assertion.15\] .* \(\*\(1\+b\)\)\[2\]==5: Unknown$ +^\[main.assertion.16\] .* \(\*\(1\+b\)\)\[2\]==0: Unknown$ +^\[main.assertion.17\] .* \*\(\*\(1\+b\)\+2\)==5: Unknown$ +^\[main.assertion.18\] .* \*\(\*\(1\+b\)\+2\)==0: Unknown$ +^\[main.assertion.19\] .* 2\[1\[b\]\]==5: Unknown$ +^\[main.assertion.20\] .* 2\[1\[b\]\]==0: Unknown$ +^\[main.assertion.21\] .* \*\(2\+1\[b\]\)==5: Unknown$ +^\[main.assertion.22\] .* \*\(2\+1\[b\]\)==0: Unknown$ +^\[main.assertion.23\] .* \*\(2\+\*\(1\+b\)\)==5: Unknown$ +^\[main.assertion.24\] .* \*\(2\+\*\(1\+b\)\)==0: Unknown$ +^\[main.assertion.25\] .* a\[0\]\[1\]==0: Unknown$ +^\[main.assertion.26\] .* a\[0\]\[1\]==1: Unknown$ +^\[main.assertion.27\] .* a\[0\]\[2\]==0: Unknown$ +^\[main.assertion.28\] .* b\[0\]\[1\]==2: Unknown$ +^\[main.assertion.29\] .* b\[0\]\[1\]==3: Unknown$ +^\[main.assertion.30\] .* b\[0\]\[2\]==2: Unknown$ +^\[main.assertion.31\] .* a\[i\]\[1\]==0: Unknown$ +^\[main.assertion.32\] .* a\[i\]\[1\]==1: Unknown$ +^\[main.assertion.33\] .* a\[1\]\[i\]==0: Unknown$ +^\[main.assertion.34\] .* a\[1\]\[i\]==1: Unknown$ +^\[main.assertion.35\] .* a\[i\]\[i\]==0: Unknown$ +^\[main.assertion.36\] .* a\[i\]\[i\]==1: Unknown$ +^\[main.assertion.37\] .* a\[j\]\[1\]==0: Unknown$ +^\[main.assertion.38\] .* a\[j\]\[1\]==1: Unknown$ +^\[main.assertion.39\] .* a\[1\]\[j\]==0: Unknown$ +^\[main.assertion.40\] .* a\[1\]\[j\]==1: Unknown$ +^\[main.assertion.41\] .* a\[j\]\[j\]==0: Unknown$ +^\[main.assertion.42\] .* a\[j\]\[j\]==1: Unknown$ +^\[main.assertion.43\] .* b\[i\]\[1\]==1: Unknown$ +^\[main.assertion.44\] .* b\[i\]\[1\]==11: Unknown$ +^\[main.assertion.45\] .* b\[1\]\[i\]==3: Unknown$ +^\[main.assertion.46\] .* b\[1\]\[i\]==11: Unknown$ +^\[main.assertion.47\] .* b\[i\]\[i\]==0: Unknown$ +^\[main.assertion.48\] .* b\[i\]\[i\]==11: Unknown$ +^\[main.assertion.49\] .* b\[j\]\[1\]==1: Unknown$ +^\[main.assertion.50\] .* b\[j\]\[1\]==11: Unknown$ +^\[main.assertion.51\] .* b\[1\]\[j\]==3: Unknown$ +^\[main.assertion.52\] .* b\[1\]\[j\]==11: Unknown$ +^\[main.assertion.53\] .* b\[j\]\[j\]==0: Unknown$ +^\[main.assertion.54\] .* b\[j\]\[j\]==11: Unknown$ +^\[main.assertion.55\] .* a\[100\]\[0\]==0: Unknown$ +^\[main.assertion.56\] .* a\[0\]\[100\]==0: Unknown$ +^\[main.assertion.57\] .* c==0: Success$ +^\[main.assertion.58\] .* c==0: Success$ +^\[main.assertion.59\] .* ei\[0\]\[1\]==1: Unknown$ +^\[main.assertion.60\] .* ei\[0\]\[1\]==0: Unknown$ +^\[main.assertion.61\] .* ei\[2\]\[1\]==0: Unknown$ +^\[main.assertion.62\] .* ei\[2\]\[1\]==1: Unknown$ +^\[main.assertion.63\] .* ej\[0\]\[1\]==0: Unknown$ +^\[main.assertion.64\] .* ej\[2\]\[1\]==0: Unknown$ +^\[main.assertion.65\] .* ek\[0\]\[1\]==0: Unknown$ +^\[main.assertion.66\] .* c==0: Success$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc index d9267ab4c21..9b8416d3b37 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc @@ -3,73 +3,73 @@ sensitivity_test_two_value_array_of_two_value_pointer.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion a\[1\]==&a0: Unknown$ -^\[main.assertion.2\] .* assertion a\[1\]==&a3: Unknown$ -^\[main.assertion.3\] .* assertion \*a\[1\]==0: Unknown$ -^\[main.assertion.4\] .* assertion \*a\[1\]==3: Unknown$ -^\[main.assertion.5\] .* assertion b\[1\]==&b1: Unknown$ -^\[main.assertion.6\] .* assertion b\[1\]==&b3: Unknown$ -^\[main.assertion.7\] .* assertion \*b\[1\]==11: Unknown$ -^\[main.assertion.8\] .* assertion \*b\[1\]==13: Unknown$ -^\[main.assertion.9\] .* assertion \*\(b\+1\)==&b1: Unknown$ -^\[main.assertion.10\] .* assertion \*\(b\+1\)==&b3: Unknown$ -^\[main.assertion.11\] .* assertion \*\(1\+b\)==&b1: Unknown$ -^\[main.assertion.12\] .* assertion \*\(1\+b\)==&b3: Unknown$ -^\[main.assertion.13\] .* assertion 1\[b\]==&b1: Unknown$ -^\[main.assertion.14\] .* assertion 1\[b\]==&b3: Unknown$ -^\[main.assertion.15\] .* assertion \*\*\(b\+1\)==11: Unknown$ -^\[main.assertion.16\] .* assertion \*\*\(b\+1\)==13: Unknown$ -^\[main.assertion.17\] .* assertion \*\*\(1\+b\)==11: Unknown$ -^\[main.assertion.18\] .* assertion \*\*\(1\+b\)==13: Unknown$ -^\[main.assertion.19\] .* assertion \*1\[b\]==11: Unknown$ -^\[main.assertion.20\] .* assertion \*1\[b\]==13: Unknown$ -^\[main.assertion.21\] .* assertion c\[0\]==&c0: Unknown$ -^\[main.assertion.22\] .* assertion c\[0\]==&c3: Unknown$ -^\[main.assertion.23\] .* assertion d\[0\]==&d0: Unknown$ -^\[main.assertion.24\] .* assertion d\[0\]==&d3: Unknown$ -^\[main.assertion.25\] .* assertion \*c\[0\]==20: Unknown$ -^\[main.assertion.26\] .* assertion \*c\[0\]==23: Unknown$ -^\[main.assertion.27\] .* assertion \*d\[0\]==30: Unknown$ -^\[main.assertion.28\] .* assertion \*d\[0\]==33: Unknown$ -^\[main.assertion.29\] .* assertion a\[i\]==&a0: Unknown$ -^\[main.assertion.30\] .* assertion a\[i\]==&a3: Unknown$ -^\[main.assertion.31\] .* assertion a\[j\]==&a0: Unknown$ -^\[main.assertion.32\] .* assertion a\[j\]==&a3: Unknown$ -^\[main.assertion.33\] .* assertion \*a\[i\]==0: Unknown$ -^\[main.assertion.34\] .* assertion \*a\[i\]==3: Unknown$ -^\[main.assertion.35\] .* assertion \*a\[j\]==0: Unknown$ -^\[main.assertion.36\] .* assertion \*a\[j\]==3: Unknown$ -^\[main.assertion.37\] .* assertion b\[i\]==&b0: Unknown$ -^\[main.assertion.38\] .* assertion b\[i\]==&b1: Unknown$ -^\[main.assertion.39\] .* assertion b\[j\]==&b0: Unknown$ -^\[main.assertion.40\] .* assertion b\[j\]==&b3: Unknown$ -^\[main.assertion.41\] .* assertion \*b\[i\]==10: Unknown$ -^\[main.assertion.42\] .* assertion \*b\[i\]==11: Unknown$ -^\[main.assertion.43\] .* assertion \*b\[j\]==10: Unknown$ -^\[main.assertion.44\] .* assertion \*b\[j\]==13: Unknown$ -^\[main.assertion.45\] .* assertion a\[100\]==&a2: Unknown$ -^\[main.assertion.46\] .* assertion \*a\[100\]==2: Unknown$ -^\[main.assertion.47\] .* assertion b\[1\]==&b1: Unknown$ -^\[main.assertion.48\] .* assertion \*b\[1\]==11: Unknown$ -^\[main.assertion.49\] .* assertion ei\[0\]==&ei1: Unknown$ -^\[main.assertion.50\] .* assertion ei\[0\]==&ei0: Unknown$ -^\[main.assertion.51\] .* assertion ei\[2\]==&ei0: Unknown$ -^\[main.assertion.52\] .* assertion ei\[2\]==&ei1: Unknown$ -^\[main.assertion.53\] .* assertion \*ei\[0\]==41: Unknown$ -^\[main.assertion.54\] .* assertion \*ei\[0\]==40: Unknown$ -^\[main.assertion.55\] .* assertion \*ei\[2\]==40: Unknown$ -^\[main.assertion.56\] .* assertion \*ei\[2\]==41: Unknown$ -^\[main.assertion.57\] .* assertion ej\[0\]==&ej0: Unknown$ -^\[main.assertion.58\] .* assertion ej\[2\]==&ej0: Unknown$ -^\[main.assertion.59\] .* assertion ej\[2\]==&ej1: Unknown$ -^\[main.assertion.60\] .* assertion \*ej\[0\]==50: Unknown$ -^\[main.assertion.61\] .* assertion \*ej\[2\]==50: Unknown$ -^\[main.assertion.62\] .* assertion \*ej\[2\]==51: Unknown$ -^\[main.assertion.63\] .* assertion ek\[0\]==&ek0: Unknown$ -^\[main.assertion.64\] .* assertion \*ek\[0\]==60: Unknown$ -^\[main\.assertion\.65\] .* assertion \*ps\[0\]==4: Unknown$ -^\[main\.assertion\.66\] .* assertion \*ps\[1\]==4: Unknown$ -^\[main\.assertion\.67\] .* assertion x==4: Success$ -^\[main\.assertion\.68\] .* assertion y==4: Failure \(if reachable\)$ +^\[main.assertion.1\] .* a\[1\]==&a0: Unknown$ +^\[main.assertion.2\] .* a\[1\]==&a3: Unknown$ +^\[main.assertion.3\] .* \*a\[1\]==0: Unknown$ +^\[main.assertion.4\] .* \*a\[1\]==3: Unknown$ +^\[main.assertion.5\] .* b\[1\]==&b1: Unknown$ +^\[main.assertion.6\] .* b\[1\]==&b3: Unknown$ +^\[main.assertion.7\] .* \*b\[1\]==11: Unknown$ +^\[main.assertion.8\] .* \*b\[1\]==13: Unknown$ +^\[main.assertion.9\] .* \*\(b\+1\)==&b1: Unknown$ +^\[main.assertion.10\] .* \*\(b\+1\)==&b3: Unknown$ +^\[main.assertion.11\] .* \*\(1\+b\)==&b1: Unknown$ +^\[main.assertion.12\] .* \*\(1\+b\)==&b3: Unknown$ +^\[main.assertion.13\] .* 1\[b\]==&b1: Unknown$ +^\[main.assertion.14\] .* 1\[b\]==&b3: Unknown$ +^\[main.assertion.15\] .* \*\*\(b\+1\)==11: Unknown$ +^\[main.assertion.16\] .* \*\*\(b\+1\)==13: Unknown$ +^\[main.assertion.17\] .* \*\*\(1\+b\)==11: Unknown$ +^\[main.assertion.18\] .* \*\*\(1\+b\)==13: Unknown$ +^\[main.assertion.19\] .* \*1\[b\]==11: Unknown$ +^\[main.assertion.20\] .* \*1\[b\]==13: Unknown$ +^\[main.assertion.21\] .* c\[0\]==&c0: Unknown$ +^\[main.assertion.22\] .* c\[0\]==&c3: Unknown$ +^\[main.assertion.23\] .* d\[0\]==&d0: Unknown$ +^\[main.assertion.24\] .* d\[0\]==&d3: Unknown$ +^\[main.assertion.25\] .* \*c\[0\]==20: Unknown$ +^\[main.assertion.26\] .* \*c\[0\]==23: Unknown$ +^\[main.assertion.27\] .* \*d\[0\]==30: Unknown$ +^\[main.assertion.28\] .* \*d\[0\]==33: Unknown$ +^\[main.assertion.29\] .* a\[i\]==&a0: Unknown$ +^\[main.assertion.30\] .* a\[i\]==&a3: Unknown$ +^\[main.assertion.31\] .* a\[j\]==&a0: Unknown$ +^\[main.assertion.32\] .* a\[j\]==&a3: Unknown$ +^\[main.assertion.33\] .* \*a\[i\]==0: Unknown$ +^\[main.assertion.34\] .* \*a\[i\]==3: Unknown$ +^\[main.assertion.35\] .* \*a\[j\]==0: Unknown$ +^\[main.assertion.36\] .* \*a\[j\]==3: Unknown$ +^\[main.assertion.37\] .* b\[i\]==&b0: Unknown$ +^\[main.assertion.38\] .* b\[i\]==&b1: Unknown$ +^\[main.assertion.39\] .* b\[j\]==&b0: Unknown$ +^\[main.assertion.40\] .* b\[j\]==&b3: Unknown$ +^\[main.assertion.41\] .* \*b\[i\]==10: Unknown$ +^\[main.assertion.42\] .* \*b\[i\]==11: Unknown$ +^\[main.assertion.43\] .* \*b\[j\]==10: Unknown$ +^\[main.assertion.44\] .* \*b\[j\]==13: Unknown$ +^\[main.assertion.45\] .* a\[100\]==&a2: Unknown$ +^\[main.assertion.46\] .* \*a\[100\]==2: Unknown$ +^\[main.assertion.47\] .* b\[1\]==&b1: Unknown$ +^\[main.assertion.48\] .* \*b\[1\]==11: Unknown$ +^\[main.assertion.49\] .* ei\[0\]==&ei1: Unknown$ +^\[main.assertion.50\] .* ei\[0\]==&ei0: Unknown$ +^\[main.assertion.51\] .* ei\[2\]==&ei0: Unknown$ +^\[main.assertion.52\] .* ei\[2\]==&ei1: Unknown$ +^\[main.assertion.53\] .* \*ei\[0\]==41: Unknown$ +^\[main.assertion.54\] .* \*ei\[0\]==40: Unknown$ +^\[main.assertion.55\] .* \*ei\[2\]==40: Unknown$ +^\[main.assertion.56\] .* \*ei\[2\]==41: Unknown$ +^\[main.assertion.57\] .* ej\[0\]==&ej0: Unknown$ +^\[main.assertion.58\] .* ej\[2\]==&ej0: Unknown$ +^\[main.assertion.59\] .* ej\[2\]==&ej1: Unknown$ +^\[main.assertion.60\] .* \*ej\[0\]==50: Unknown$ +^\[main.assertion.61\] .* \*ej\[2\]==50: Unknown$ +^\[main.assertion.62\] .* \*ej\[2\]==51: Unknown$ +^\[main.assertion.63\] .* ek\[0\]==&ek0: Unknown$ +^\[main.assertion.64\] .* \*ek\[0\]==60: Unknown$ +^\[main\.assertion\.65\] .* \*ps\[0\]==4: Unknown$ +^\[main\.assertion\.66\] .* \*ps\[1\]==4: Unknown$ +^\[main\.assertion\.67\] .* x==4: Success$ +^\[main\.assertion\.68\] .* y==4: Failure \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-array/test.desc index aed3958cf63..c7daafa0c23 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-array/test.desc @@ -3,37 +3,37 @@ sensitivity_test_two_value_array.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion a\[1\]==0: Unknown$ -^\[main.assertion.2\] .* assertion a\[1\]==1: Unknown$ -^\[main.assertion.3\] .* assertion b\[1\]==0: Unknown$ -^\[main.assertion.4\] .* assertion b\[1\]==1: Unknown$ -^\[main.assertion.5\] .* assertion \*\(b\+1\)==0: Unknown$ -^\[main.assertion.6\] .* assertion \*\(b\+1\)==1: Unknown$ -^\[main.assertion.7\] .* assertion \*\(1\+b\)==0: Unknown$ -^\[main.assertion.8\] .* assertion \*\(1\+b\)==1: Unknown$ -^\[main.assertion.9\] .* assertion 1\[b\]==0: Unknown$ -^\[main.assertion.10\] .* assertion 1\[b\]==1: Unknown$ -^\[main.assertion.11\] .* assertion c\[0\]==0: Unknown$ -^\[main.assertion.12\] .* assertion c\[0\]==1: Unknown$ -^\[main.assertion.13\] .* assertion d\[0\]==0: Unknown$ -^\[main.assertion.14\] .* assertion d\[0\]==2: Unknown$ -^\[main.assertion.15\] .* assertion d\[1\]==0: Unknown$ -^\[main.assertion.16\] .* assertion a\[i\]==0: Unknown$ -^\[main.assertion.17\] .* assertion a\[i\]==1: Unknown$ -^\[main.assertion.18\] .* assertion a\[j\]==0: Unknown$ -^\[main.assertion.19\] .* assertion a\[j\]==1: Unknown$ -^\[main.assertion.20\] .* assertion b\[i\]==1: Unknown$ -^\[main.assertion.21\] .* assertion b\[i\]==0: Unknown$ -^\[main.assertion.22\] .* assertion b\[j\]==0: Unknown$ -^\[main.assertion.23\] .* assertion b\[j\]==1: Unknown$ -^\[main.assertion.24\] .* assertion a\[100\]==0: Unknown$ -^\[main.assertion.25\] .* assertion b\[1\]==0: Unknown$ -^\[main.assertion.26\] .* assertion ei\[0\]==1: Unknown$ -^\[main.assertion.27\] .* assertion ei\[0\]==0: Unknown$ -^\[main.assertion.28\] .* assertion ei\[2\]==0: Unknown$ -^\[main.assertion.29\] .* assertion ei\[2\]==1: Unknown$ -^\[main.assertion.30\] .* assertion ej\[0\]==0: Unknown$ -^\[main.assertion.31\] .* assertion ej\[2\]==0: Unknown$ -^\[main.assertion.32\] .* assertion ek\[0\]==0: Unknown$ +^\[main.assertion.1\] .* a\[1\]==0: Unknown$ +^\[main.assertion.2\] .* a\[1\]==1: Unknown$ +^\[main.assertion.3\] .* b\[1\]==0: Unknown$ +^\[main.assertion.4\] .* b\[1\]==1: Unknown$ +^\[main.assertion.5\] .* \*\(b\+1\)==0: Unknown$ +^\[main.assertion.6\] .* \*\(b\+1\)==1: Unknown$ +^\[main.assertion.7\] .* \*\(1\+b\)==0: Unknown$ +^\[main.assertion.8\] .* \*\(1\+b\)==1: Unknown$ +^\[main.assertion.9\] .* 1\[b\]==0: Unknown$ +^\[main.assertion.10\] .* 1\[b\]==1: Unknown$ +^\[main.assertion.11\] .* c\[0\]==0: Unknown$ +^\[main.assertion.12\] .* c\[0\]==1: Unknown$ +^\[main.assertion.13\] .* d\[0\]==0: Unknown$ +^\[main.assertion.14\] .* d\[0\]==2: Unknown$ +^\[main.assertion.15\] .* d\[1\]==0: Unknown$ +^\[main.assertion.16\] .* a\[i\]==0: Unknown$ +^\[main.assertion.17\] .* a\[i\]==1: Unknown$ +^\[main.assertion.18\] .* a\[j\]==0: Unknown$ +^\[main.assertion.19\] .* a\[j\]==1: Unknown$ +^\[main.assertion.20\] .* b\[i\]==1: Unknown$ +^\[main.assertion.21\] .* b\[i\]==0: Unknown$ +^\[main.assertion.22\] .* b\[j\]==0: Unknown$ +^\[main.assertion.23\] .* b\[j\]==1: Unknown$ +^\[main.assertion.24\] .* a\[100\]==0: Unknown$ +^\[main.assertion.25\] .* b\[1\]==0: Unknown$ +^\[main.assertion.26\] .* ei\[0\]==1: Unknown$ +^\[main.assertion.27\] .* ei\[0\]==0: Unknown$ +^\[main.assertion.28\] .* ei\[2\]==0: Unknown$ +^\[main.assertion.29\] .* ei\[2\]==1: Unknown$ +^\[main.assertion.30\] .* ej\[0\]==0: Unknown$ +^\[main.assertion.31\] .* ej\[2\]==0: Unknown$ +^\[main.assertion.32\] .* ek\[0\]==0: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc index b4af7c15ab1..4a96ad8909c 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc @@ -3,27 +3,27 @@ sensitivity_test_two_value_pointer_to_two_value_array.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] .* assertion p==&a\[0\]: Unknown$ -^\[main\.assertion\.2\] .* assertion \*p==1: Unknown$ -^\[main\.assertion\.3\] .* assertion p\[1\]==2: Unknown$ -^\[main\.assertion\.4\] .* assertion 1\[p\]==2: Unknown$ -^\[main\.assertion\.5\] .* assertion \*\(p\+1\)==2: Unknown$ -^\[main\.assertion\.6\] .* assertion \*\(1\+p\)==2: Unknown$ -^\[main\.assertion\.7\] .* assertion \*\(p-1\)==1: Unknown$ -^\[main\.assertion\.8\] .* assertion q==p\+1: Unknown$ -^\[main\.assertion\.9\] .* assertion \*q==2: Unknown$ -^\[main\.assertion\.10\] .* assertion q-p==x: Unknown$ -^\[main\.assertion\.11\] .* assertion a\[1\]==4: Unknown$ -^\[main\.assertion\.12\] .* assertion a\[1\]==5: Unknown$ -^\[main\.assertion\.13\] .* assertion a\[1\]==6: Unknown$ -^\[main\.assertion\.14\] .* assertion a\[1\]==7: Unknown$ -^\[main\.assertion\.15\] .* assertion \*r==2: Unknown$ -^\[main\.assertion\.16\] .* assertion \*r==1: Unknown$ -^\[main\.assertion\.17\] .* assertion \*s==0: Unknown$ -^\[main\.assertion\.18\] .* assertion \*s==1: Unknown$ -^\[main\.assertion\.19\] .* assertion t==p\+i: Unknown$ -^\[main\.assertion\.20\] .* assertion t-p==y: Unknown$ -^\[main\.assertion\.21\] .* assertion a\[i\]==5: Unknown$ -^\[main\.assertion\.22\] .* assertion a\[1\]==5: Unknown$ +^\[main\.assertion\.1\] .* p==&a\[0\]: Unknown$ +^\[main\.assertion\.2\] .* \*p==1: Unknown$ +^\[main\.assertion\.3\] .* p\[1\]==2: Unknown$ +^\[main\.assertion\.4\] .* 1\[p\]==2: Unknown$ +^\[main\.assertion\.5\] .* \*\(p\+1\)==2: Unknown$ +^\[main\.assertion\.6\] .* \*\(1\+p\)==2: Unknown$ +^\[main\.assertion\.7\] .* \*\(p-1\)==1: Unknown$ +^\[main\.assertion\.8\] .* q==p\+1: Unknown$ +^\[main\.assertion\.9\] .* \*q==2: Unknown$ +^\[main\.assertion\.10\] .* q-p==x: Unknown$ +^\[main\.assertion\.11\] .* a\[1\]==4: Unknown$ +^\[main\.assertion\.12\] .* a\[1\]==5: Unknown$ +^\[main\.assertion\.13\] .* a\[1\]==6: Unknown$ +^\[main\.assertion\.14\] .* a\[1\]==7: Unknown$ +^\[main\.assertion\.15\] .* \*r==2: Unknown$ +^\[main\.assertion\.16\] .* \*r==1: Unknown$ +^\[main\.assertion\.17\] .* \*s==0: Unknown$ +^\[main\.assertion\.18\] .* \*s==1: Unknown$ +^\[main\.assertion\.19\] .* t==p\+i: Unknown$ +^\[main\.assertion\.20\] .* t-p==y: Unknown$ +^\[main\.assertion\.21\] .* a\[i\]==5: Unknown$ +^\[main\.assertion\.22\] .* a\[1\]==5: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/test.desc index 8ea26dbd7e9..1b6643766e9 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/test.desc @@ -3,11 +3,11 @@ sensitivity_test_two_value_pointer_to_two_value_pointer.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion \*\*x==0: Unknown$ -^\[main.assertion.2\] .* assertion \*\*x==1: Unknown$ -^\[main.assertion.3\] .* assertion \*\*x==1: Unknown$ -^\[main.assertion.4\] .* assertion \*\*x==0: Unknown$ -^\[main.assertion.5\] .* assertion a==2: Unknown$ -^\[main.assertion.6\] .* assertion a==1: Unknown$ +^\[main.assertion.1\] .* \*\*x==0: Unknown$ +^\[main.assertion.2\] .* \*\*x==1: Unknown$ +^\[main.assertion.3\] .* \*\*x==1: Unknown$ +^\[main.assertion.4\] .* \*\*x==0: Unknown$ +^\[main.assertion.5\] .* a==2: Unknown$ +^\[main.assertion.6\] .* a==1: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/test.desc index 17853721fc2..57b974c1619 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/test.desc @@ -3,11 +3,11 @@ sensitivity_test_two_value_pointer_to_two_value_struct.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion \(\*p\).a==0: Unknown$ -^\[main.assertion.2\] .* assertion \(\*p\).a==1: Unknown$ -^\[main.assertion.3\] .* assertion p->a==0: Unknown$ -^\[main.assertion.4\] .* assertion p->a==1: Unknown$ -^\[main.assertion.5\] .* assertion p->b==2.0: Unknown$ -^\[main.assertion.6\] .* assertion p->b==1.0: Unknown$ +^\[main.assertion.1\] .* \(\*p\).a==0: Unknown$ +^\[main.assertion.2\] .* \(\*p\).a==1: Unknown$ +^\[main.assertion.3\] .* p->a==0: Unknown$ +^\[main.assertion.4\] .* p->a==1: Unknown$ +^\[main.assertion.5\] .* p->b==2.0: Unknown$ +^\[main.assertion.6\] .* p->b==1.0: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer/test.desc index 97be4873c1a..f55b2fae94d 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer/test.desc @@ -3,19 +3,19 @@ sensitivity_test_two_value_pointer.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x==&a: Unknown$ -^\[main.assertion.2\] .* assertion x==&b: Unknown$ -^\[main.assertion.3\] .* assertion x==x2: Unknown$ -^\[main.assertion.4\] .* assertion x==y: Unknown$ -^\[main.assertion.5\] .* assertion \*x==0: Unknown$ -^\[main.assertion.6\] .* assertion \*x==1: Unknown$ -^\[main.assertion.7\] .* assertion \*x==1: Unknown$ -^\[main.assertion.8\] .* assertion \*x==0: Unknown$ -^\[main.assertion.9\] .* assertion a==2: Unknown$ -^\[main.assertion.10\] .* assertion a==0: Unknown$ -^\[main.assertion.11\] .* assertion x==&a: Unknown$ -^\[main.assertion.12\] .* assertion \*x==0: Unknown$ -^\[main.assertion.13\] .* assertion x==&a: Unknown$ -^\[main.assertion.14\] .* assertion x==&b: Unknown$ +^\[main.assertion.1\] .* x==&a: Unknown$ +^\[main.assertion.2\] .* x==&b: Unknown$ +^\[main.assertion.3\] .* x==x2: Unknown$ +^\[main.assertion.4\] .* x==y: Unknown$ +^\[main.assertion.5\] .* \*x==0: Unknown$ +^\[main.assertion.6\] .* \*x==1: Unknown$ +^\[main.assertion.7\] .* \*x==1: Unknown$ +^\[main.assertion.8\] .* \*x==0: Unknown$ +^\[main.assertion.9\] .* a==2: Unknown$ +^\[main.assertion.10\] .* a==0: Unknown$ +^\[main.assertion.11\] .* x==&a: Unknown$ +^\[main.assertion.12\] .* \*x==0: Unknown$ +^\[main.assertion.13\] .* x==&a: Unknown$ +^\[main.assertion.14\] .* x==&b: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/test.desc index 2276f289deb..66350a644c7 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/test.desc @@ -3,22 +3,22 @@ sensitivity_test_two_value_struct_of_two_value_array.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x.a\[0\]==0: Unknown$ -^\[main.assertion.2\] .* assertion \*\(x.a\+0\)==0: Unknown$ -^\[main.assertion.3\] .* assertion \*\(0\+x.a\)==0: Unknown$ -^\[main.assertion.4\] .* assertion 0\[x.a\]==0: Unknown$ -^\[main.assertion.5\] .* assertion x.a\[0\]==0: Unknown$ -^\[main.assertion.6\] .* assertion x.a\[1\]==1: Unknown$ -^\[main.assertion.7\] .* assertion x.b\[0\]==3.0f: Unknown$ -^\[main.assertion.8\] .* assertion x.a\[0\]==0: Unknown$ -^\[main.assertion.9\] .* assertion x.a\[1\]==1: Unknown$ -^\[main.assertion.10\] .* assertion x.b\[2\]>0.0f: Unknown$ -^\[main.assertion.11\] .* assertion x.b\[2\]==15.0f: Unknown$ -^\[main.assertion.12\] .* assertion x.b\[2\]==1.0f: Unknown$ -^\[main.assertion.13\] .* assertion x.b\[0\]==3.0f: Unknown$ -^\[main.assertion.14\] .* assertion x.a\[0\]<12: Unknown$ -^\[main.assertion.15\] .* assertion x.a\[0\]>2: Unknown$ -^\[main.assertion.16\] .* assertion x.a\[0\]==0: Unknown$ -^\[main.assertion.17\] .* assertion x.a\[1\]==1: Unknown$ +^\[main.assertion.1\] .* x.a\[0\]==0: Unknown$ +^\[main.assertion.2\] .* \*\(x.a\+0\)==0: Unknown$ +^\[main.assertion.3\] .* \*\(0\+x.a\)==0: Unknown$ +^\[main.assertion.4\] .* 0\[x.a\]==0: Unknown$ +^\[main.assertion.5\] .* x.a\[0\]==0: Unknown$ +^\[main.assertion.6\] .* x.a\[1\]==1: Unknown$ +^\[main.assertion.7\] .* x.b\[0\]==3.0f: Unknown$ +^\[main.assertion.8\] .* x.a\[0\]==0: Unknown$ +^\[main.assertion.9\] .* x.a\[1\]==1: Unknown$ +^\[main.assertion.10\] .* x.b\[2\]>0.0f: Unknown$ +^\[main.assertion.11\] .* x.b\[2\]==15.0f: Unknown$ +^\[main.assertion.12\] .* x.b\[2\]==1.0f: Unknown$ +^\[main.assertion.13\] .* x.b\[0\]==3.0f: Unknown$ +^\[main.assertion.14\] .* x.a\[0\]<12: Unknown$ +^\[main.assertion.15\] .* x.a\[0\]>2: Unknown$ +^\[main.assertion.16\] .* x.a\[0\]==0: Unknown$ +^\[main.assertion.17\] .* x.a\[1\]==1: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/test.desc index abb9d40d9ae..054effb0edb 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/test.desc @@ -3,31 +3,31 @@ sensitivity_test_two_value_struct_of_two_value_pointer.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x.a==&a1: Unknown$ -^\[main.assertion.2\] .* assertion x.a==&a2: Unknown$ -^\[main.assertion.3\] .* assertion x.b==&b1: Unknown$ -^\[main.assertion.4\] .* assertion x.b==&b2: Unknown$ -^\[main.assertion.5\] .* assertion \*x.a==0: Unknown$ -^\[main.assertion.6\] .* assertion \*x.a==100: Unknown$ -^\[main.assertion.7\] .* assertion \*x.b==10.0f: Unknown$ -^\[main.assertion.8\] .* assertion \*x.b==110.0f: Unknown$ -^\[main.assertion.9\] .* assertion x.a==&a1: Unknown$ -^\[main.assertion.10\] .* assertion x.a==&a2: Unknown$ -^\[main.assertion.11\] .* assertion \*x.a==0: Unknown$ -^\[main.assertion.12\] .* assertion \*x.a==100: Unknown$ -^\[main.assertion.13\] .* assertion x.a==&a1: Unknown$ -^\[main.assertion.14\] .* assertion x.b==&b2: Unknown$ -^\[main.assertion.15\] .* assertion x.b==&b3: Unknown$ -^\[main.assertion.16\] .* assertion \*x.a==0: Unknown$ -^\[main.assertion.17\] .* assertion \*x.b==11.0f: Unknown$ -^\[main.assertion.18\] .* assertion \*x.b==12.0f: Unknown$ -^\[main.assertion.19\] .* assertion x.a==&a2: Unknown$ -^\[main.assertion.20\] .* assertion x.a==&a3: Unknown$ -^\[main.assertion.21\] .* assertion x.b==&b3: Unknown$ -^\[main.assertion.22\] .* assertion x.b==&b4: Unknown$ -^\[main.assertion.23\] .* assertion \*x.a==1: Unknown$ -^\[main.assertion.24\] .* assertion \*x.a==2: Unknown$ -^\[main.assertion.25\] .* assertion \*x.b==12.0f: Unknown$ -^\[main.assertion.26\] .* assertion \*x.b==13.0f: Unknown$ +^\[main.assertion.1\] .* x.a==&a1: Unknown$ +^\[main.assertion.2\] .* x.a==&a2: Unknown$ +^\[main.assertion.3\] .* x.b==&b1: Unknown$ +^\[main.assertion.4\] .* x.b==&b2: Unknown$ +^\[main.assertion.5\] .* \*x.a==0: Unknown$ +^\[main.assertion.6\] .* \*x.a==100: Unknown$ +^\[main.assertion.7\] .* \*x.b==10.0f: Unknown$ +^\[main.assertion.8\] .* \*x.b==110.0f: Unknown$ +^\[main.assertion.9\] .* x.a==&a1: Unknown$ +^\[main.assertion.10\] .* x.a==&a2: Unknown$ +^\[main.assertion.11\] .* \*x.a==0: Unknown$ +^\[main.assertion.12\] .* \*x.a==100: Unknown$ +^\[main.assertion.13\] .* x.a==&a1: Unknown$ +^\[main.assertion.14\] .* x.b==&b2: Unknown$ +^\[main.assertion.15\] .* x.b==&b3: Unknown$ +^\[main.assertion.16\] .* \*x.a==0: Unknown$ +^\[main.assertion.17\] .* \*x.b==11.0f: Unknown$ +^\[main.assertion.18\] .* \*x.b==12.0f: Unknown$ +^\[main.assertion.19\] .* x.a==&a2: Unknown$ +^\[main.assertion.20\] .* x.a==&a3: Unknown$ +^\[main.assertion.21\] .* x.b==&b3: Unknown$ +^\[main.assertion.22\] .* x.b==&b4: Unknown$ +^\[main.assertion.23\] .* \*x.a==1: Unknown$ +^\[main.assertion.24\] .* \*x.a==2: Unknown$ +^\[main.assertion.25\] .* \*x.b==12.0f: Unknown$ +^\[main.assertion.26\] .* \*x.b==13.0f: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/test.desc index b541110804e..6d9cd97289c 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/test.desc @@ -3,16 +3,16 @@ sensitivity_test_two_value_struct_of_two_value_struct.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x.s1.a==0: Unknown$ -^\[main.assertion.2\] .* assertion x.s2.b==3.0f: Unknown$ -^\[main.assertion.3\] .* assertion x.s1.a==0: Unknown$ -^\[main.assertion.4\] .* assertion x.s1.a==10: Unknown$ -^\[main.assertion.5\] .* assertion x.s1.b==1.0f: Unknown$ -^\[main.assertion.6\] .* assertion x.s2.b==3.0f: Unknown$ -^\[main.assertion.7\] .* assertion x.s2.b==0.0f: Unknown$ -^\[main.assertion.8\] .* assertion x.s1.a==20: Unknown$ -^\[main.assertion.9\] .* assertion x.s1.a<30: Unknown$ -^\[main.assertion.10\] .* assertion x.s2.a==22: Unknown$ -^\[main.assertion.11\] .* assertion x.s2.a<30: Unknown$ +^\[main.assertion.1\] .* x.s1.a==0: Unknown$ +^\[main.assertion.2\] .* x.s2.b==3.0f: Unknown$ +^\[main.assertion.3\] .* x.s1.a==0: Unknown$ +^\[main.assertion.4\] .* x.s1.a==10: Unknown$ +^\[main.assertion.5\] .* x.s1.b==1.0f: Unknown$ +^\[main.assertion.6\] .* x.s2.b==3.0f: Unknown$ +^\[main.assertion.7\] .* x.s2.b==0.0f: Unknown$ +^\[main.assertion.8\] .* x.s1.a==20: Unknown$ +^\[main.assertion.9\] .* x.s1.a<30: Unknown$ +^\[main.assertion.10\] .* x.s2.a==22: Unknown$ +^\[main.assertion.11\] .* x.s2.a<30: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-struct/test.desc index 7835ecb2c41..962873ac044 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-struct/test.desc @@ -3,14 +3,14 @@ sensitivity_test_two_value_struct.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* assertion x.a==0: Unknown$ -^\[main.assertion.2\] .* assertion x.a==1: Unknown$ -^\[main.assertion.3\] .* assertion x.a==0: Unknown$ -^\[main.assertion.4\] .* assertion x.a==0: Unknown$ -^\[main.assertion.5\] .* assertion x.b>0.0f: Unknown$ -^\[main.assertion.6\] .* assertion x.b==1.0f: Unknown$ -^\[main.assertion.7\] .* assertion x.a<2: Unknown$ -^\[main.assertion.8\] .* assertion x.a>2: Unknown$ -^\[main.assertion.9\] .* assertion x.a==1: Unknown$ +^\[main.assertion.1\] .* x.a==0: Unknown$ +^\[main.assertion.2\] .* x.a==1: Unknown$ +^\[main.assertion.3\] .* x.a==0: Unknown$ +^\[main.assertion.4\] .* x.a==0: Unknown$ +^\[main.assertion.5\] .* x.b>0.0f: Unknown$ +^\[main.assertion.6\] .* x.b==1.0f: Unknown$ +^\[main.assertion.7\] .* x.a<2: Unknown$ +^\[main.assertion.8\] .* x.a>2: Unknown$ +^\[main.assertion.9\] .* x.a==1: Unknown$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/unreachable_assertions_01/main.c b/regression/goto-analyzer/unreachable_assertions_01/main.c index 53fea7e7493..d89733963f7 100644 --- a/regression/goto-analyzer/unreachable_assertions_01/main.c +++ b/regression/goto-analyzer/unreachable_assertions_01/main.c @@ -10,19 +10,19 @@ int main (int argc, char **argv) int y = nondet_int(); if (a == b) - assert(0); // Trivial false + __CPROVER_assert(0, "0"); // Trivial false if (a == b) - assert(1); // Trivial true + __CPROVER_assert(1, "1"); // Trivial true if (a == b) - assert(x == y); // Undetermined + __CPROVER_assert(x == y, "x == y"); // Undetermined if (a == b) - assert(!(x == y) || (x + 1 + a == b + y)); // Non-trivial true + __CPROVER_assert(!(x == y) || (x + 1 + a == b + y), "!(x == y) || (x + 1 + a == b + y)"); // Non-trivial true if (a == b) - assert(!(!(x == y) || (x + 1 + a == b + y))); // Non-trivial false + __CPROVER_assert(!(!(x == y) || (x + 1 + a == b + y)), "!(!(x == y) || (x + 1 + a == b + y)"); // Non-trivial false return 0; } diff --git a/regression/goto-analyzer/unreachable_assertions_01/test.desc b/regression/goto-analyzer/unreachable_assertions_01/test.desc index 1b8a2a4405b..2125fa276e1 100644 --- a/regression/goto-analyzer/unreachable_assertions_01/test.desc +++ b/regression/goto-analyzer/unreachable_assertions_01/test.desc @@ -1,11 +1,11 @@ CORE main.c --verify --variable -^\[main.assertion.1\] file main.c line 13 function main, assertion 0: Success \(unreachable\)$ -^\[main.assertion.2\] file main.c line 16 function main, assertion 1: Success \(unreachable\)$ -^\[main.assertion.3\] file main.c line 19 function main, assertion x == y: Success \(unreachable\)$ -^\[main.assertion.4\] file main.c line 22 function main, assertion !\(x == y\) || \(x + 1 + a == b + y\): Success \(unreachable\)$ -^\[main.assertion.5\] file main.c line 25 function main, assertion !\(!\(x == y\) || \(x + 1 + a == b + y\)\): Success \(unreachable\)$ +^\[main\.assertion\.1\] .* 0: Success \(unreachable\)$ +^\[main\.assertion\.2\] .* 1: Success \(unreachable\)$ +^\[main\.assertion\.3\] .* x == y: Success \(unreachable\)$ +^\[main\.assertion\.4\] .* !\(x == y\) || \(x + 1 + a == b + y\): Success \(unreachable\)$ +^\[main\.assertion\.5\] .* !\(!\(x == y\) || \(x + 1 + a == b + y\)\): Success \(unreachable\)$ ^EXIT=0$ ^SIGNAL=0$ -- From 0f51650eb3d9f70cd0c376bff07cd503c87e6cd8 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 5 May 2017 15:48:48 +0100 Subject: [PATCH 120/129] Use Behaviour Driven Design testing for abstract object merge --- .../abstract_object/merge.cpp | 76 +++++++++++-------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/unit/analyses/variable-sensitivity/abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp index 72f6085f501..aa33c9bfcf5 100644 --- a/unit/analyses/variable-sensitivity/abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp @@ -11,26 +11,26 @@ #include #include -TEST_CASE("merge_abstract_object", +SCENARIO("merge_abstract_object", "[core][analyses][variable-sensitivity][abstract_object][merge]") { - SECTION("abstract object merge with abstract object") + GIVEN("Two abstract objects of type pointer") { const typet object_type=signedbv_typet(32); - SECTION("merging top with...") + WHEN("Both are top") { abstract_object_pointert op1= std::make_shared(object_type, true, false); - SECTION("top") - { - abstract_object_pointert op2= - std::make_shared(object_type, true, false); + abstract_object_pointert op2= + std::make_shared(object_type, true, false); - bool modifications; - abstract_object_pointert result= - abstract_objectt::merge(op1, op2, modifications); + bool modifications; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modifications); + THEN("The result is the original abstract object") + { // Simple correctness of merge REQUIRE_FALSE(modifications); REQUIRE(result->is_top()); @@ -39,15 +39,21 @@ TEST_CASE("merge_abstract_object", // Is optimal REQUIRE(op1==result); } - SECTION("bottom") - { - abstract_object_pointert op2= - std::make_shared(object_type, false, true); + } + WHEN("The first is top, the second is bottom") + { + abstract_object_pointert op1= + std::make_shared(object_type, true, false); - bool modifications; - abstract_object_pointert result= + abstract_object_pointert op2= + std::make_shared(object_type, false, true); + + bool modifications; + abstract_object_pointert result= abstract_objectt::merge(op1, op2, modifications); + THEN("The result is the original abstract object") + { // Simple correctness of merge REQUIRE_FALSE(modifications); REQUIRE(result->is_top()); @@ -57,20 +63,19 @@ TEST_CASE("merge_abstract_object", REQUIRE(op1==result); } } - SECTION("merging bottom with...") + WHEN("The first is bottom and the second is top") { abstract_object_pointert op1= - std::make_shared(object_type, false, true); + std::make_shared(object_type, false, true); + abstract_object_pointert op2= + std::make_shared(object_type, true, false); - SECTION("top") - { - abstract_object_pointert op2= - std::make_shared(object_type, true, false); - - bool modifications; - abstract_object_pointert result= - abstract_objectt::merge(op1, op2, modifications); + bool modifications; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modifications); + THEN("The result is top and a new abstract object") + { // Simple correctness of merge REQUIRE(modifications); REQUIRE(result->is_top()); @@ -78,15 +83,20 @@ TEST_CASE("merge_abstract_object", REQUIRE_FALSE(op1==result); } - SECTION("bottom") - { - abstract_object_pointert op2= - std::make_shared(object_type, false, true); + } + WHEN("Both are bottom") + { + abstract_object_pointert op1= + std::make_shared(object_type, false, true); + abstract_object_pointert op2= + std::make_shared(object_type, false, true); - bool modifications; - abstract_object_pointert result= - abstract_objectt::merge(op1, op2, modifications); + bool modifications; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modifications); + THEN("The result is the original abstract object") + { // Simple correctness of merge REQUIRE_FALSE(modifications); REQUIRE_FALSE(result->is_top()); From 6191fb252e4c83a99c4695ea912839635c84c36d Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 5 May 2017 16:34:48 +0100 Subject: [PATCH 121/129] Struct and array AO unit tests using behaviour driven design Removed some unnecessary debug information from the tests --- .../constant_array_abstract_object/merge.cpp | 123 +++++++--------- .../full_struct_abstract_object/merge.cpp | 136 ++++++++---------- 2 files changed, 116 insertions(+), 143 deletions(-) diff --git a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp index 6ab3e037ed2..b3d3ccdc1c8 100644 --- a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp @@ -46,10 +46,12 @@ class array_utilt const namespacet ns; }; -TEST_CASE("merge_constant_array_abstract_object", +SCENARIO("merge_constant_array_abstract_object", "[core]" "[analyses][variable-sensitivity][constant_array_abstract_object][merge]") { + GIVEN("Two arrays of size 3, whose first elements are the same") + { // int val1[3] = {1, 2, 3} exprt val1= array_exprt( @@ -88,80 +90,63 @@ TEST_CASE("merge_constant_array_abstract_object", abstract_object_pointert result; bool modified=false; - - SECTION("constant array AO merge with constant array AO") + WHEN("Merging two constant array AOs with the same array") { - SECTION("merge array with...") - { - auto op1= - std::make_shared(val1, enviroment, ns); - - SECTION("same value") - { - INFO(val1.op0().type().id_string()); - - auto op2= - std::make_shared( - val1, enviroment, ns); - - REQUIRE(util.read_index(op1, i1)==val1.op1()); - REQUIRE(util.read_index(op1, i0)==val1.op0()); - - INFO(i2.pretty()); - - const exprt &arr_val2=util.read_index(op1, i2); - INFO(arr_val2.pretty()); + auto op1= + std::make_shared(val1, enviroment, ns); + auto op2= + std::make_shared(val1, enviroment, ns); - REQUIRE(arr_val2==val1.op2()); + result=abstract_objectt::merge(op1, op2, modified); - REQUIRE(util.read_index(op2, i0)==val1.op0()); - REQUIRE(util.read_index(op2, i1)==val1.op1()); - REQUIRE(util.read_index(op2, i2)==val1.op2()); - - result=abstract_objectt::merge(op1, op2, modified); + const auto &cast_result= + std::dynamic_pointer_cast( + result); + THEN("The original constant array AO should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==val1.op0()); + REQUIRE(util.read_index(cast_result, i1)==val1.op1()); + REQUIRE(util.read_index(cast_result, i2)==val1.op2()); + + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging two constant array AOs with different value arrays") + { + auto op1= + std::make_shared(val1, enviroment, ns); + auto op2= + std::make_shared(val2, enviroment, ns); - const auto &cast_result= - std::dynamic_pointer_cast( - result); - // Though we may become top or bottom, the type should be unchanged - REQUIRE(cast_result); + result=abstract_objectt::merge(op1, op2, modified); - // Correctness of merge - REQUIRE_FALSE(modified); - REQUIRE_FALSE(cast_result->is_top()); - REQUIRE_FALSE(cast_result->is_bottom()); - REQUIRE(util.read_index(cast_result, i0)==val1.op0()); - REQUIRE(util.read_index(cast_result, i1)==val1.op1()); - REQUIRE(util.read_index(cast_result, i2)==val1.op2()); + const auto &cast_result= + std::dynamic_pointer_cast(result); - // Is optimal - REQUIRE(result==op1); - } - SECTION("different array") - { - abstract_object_pointert op2= - std::make_shared( - val2, enviroment, ns); - - result=abstract_objectt::merge(op1, op2, modified); - - const auto &cast_result= - std::dynamic_pointer_cast( - result); - // Though we may become top or bottom, the type should be unchanged - REQUIRE(cast_result); - - // Correctness of merge - REQUIRE(modified); - REQUIRE_FALSE(cast_result->is_top()); - REQUIRE_FALSE(cast_result->is_bottom()); - REQUIRE(util.read_index(cast_result, i0)==val1.op0()); - REQUIRE(util.read_index(cast_result, i1)==nil_exprt()); - REQUIRE(util.read_index(cast_result, i2)==nil_exprt()); - - - // Since it has modified, we definitely shouldn't be reusing the pointer - REQUIRE_FALSE(result==op1); + THEN("A new constant array AO whose first value is the same and " + "the other two are top") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==val1.op0()); + REQUIRE(util.read_index(cast_result, i1)==nil_exprt()); + REQUIRE(util.read_index(cast_result, i2)==nil_exprt()); + + // Since it has modified, we definitely shouldn't be reusing the pointer + REQUIRE_FALSE(result==op1); } } } diff --git a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp index bb7f5553393..868f47ccf7b 100644 --- a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp @@ -82,81 +82,64 @@ class struct_utilt const namespacet ns; }; -TEST_CASE("merge_full_struct_abstract_object", +SCENARIO("merge_full_struct_abstract_object", "[core]" "[analyses][variable-sensitivity][full_struct_abstract_object][merge]") { - // int val1[3] = {1, 2, 3} - struct_typet struct_type; - struct_union_typet::componentt comp_a("a", integer_typet()); - struct_union_typet::componentt comp_b("b", integer_typet()); - struct_union_typet::componentt comp_c("c", integer_typet()); - struct_type.components().push_back(comp_a); - struct_type.components().push_back(comp_b); - struct_type.components().push_back(comp_c); - - struct_exprt val1(struct_type); - val1.operands().push_back(constant_exprt::integer_constant(1)); - val1.operands().push_back(constant_exprt::integer_constant(2)); - val1.operands().push_back(constant_exprt::integer_constant(3)); - - // int val2[3] = {1, 4, 5} - struct_exprt val2(struct_type); - val2.operands().push_back(constant_exprt::integer_constant(1)); - val2.operands().push_back(constant_exprt::integer_constant(4)); - val2.operands().push_back(constant_exprt::integer_constant(5)); - - // index_exprt for reading from an array - const member_exprt a(nil_exprt(), "a"); - const member_exprt b(nil_exprt(), "b"); - const member_exprt c(nil_exprt(), "c"); - - abstract_environmentt enviroment; - symbol_tablet symbol_table; - namespacet ns(symbol_table); - - optionst options; - options.set_option("pointers", true); - options.set_option("arrays", true); - options.set_option("structs", true); - variable_sensitivity_object_factoryt::instance().set_options(options); - - struct_utilt util(enviroment, ns); - - abstract_object_pointert result; - bool modified=false; - - SECTION("constant struct AO merge with constant struct AO") + GIVEN("Two structs with 3 components, whose 1st component are the same") { - SECTION("merge struct with...") + // struct val1 = {.a = 1, .b = 2, .c = 3} + struct_typet struct_type; + struct_union_typet::componentt comp_a("a", integer_typet()); + struct_union_typet::componentt comp_b("b", integer_typet()); + struct_union_typet::componentt comp_c("c", integer_typet()); + struct_type.components().push_back(comp_a); + struct_type.components().push_back(comp_b); + struct_type.components().push_back(comp_c); + + struct_exprt val1(struct_type); + val1.operands().push_back(constant_exprt::integer_constant(1)); + val1.operands().push_back(constant_exprt::integer_constant(2)); + val1.operands().push_back(constant_exprt::integer_constant(3)); + + // struct val1 = {.a = 1, .b = 4, .c = 5} + struct_exprt val2(struct_type); + val2.operands().push_back(constant_exprt::integer_constant(1)); + val2.operands().push_back(constant_exprt::integer_constant(4)); + val2.operands().push_back(constant_exprt::integer_constant(5)); + + // index_exprt for reading from an array + const member_exprt a(nil_exprt(), "a"); + const member_exprt b(nil_exprt(), "b"); + const member_exprt c(nil_exprt(), "c"); + + abstract_environmentt enviroment; + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + optionst options; + options.set_option("pointers", true); + options.set_option("arrays", true); + options.set_option("structs", true); + variable_sensitivity_object_factoryt::instance().set_options(options); + + struct_utilt util(enviroment, ns); + + abstract_object_pointert result; + bool modified=false; + + WHEN("Merging two constant struct AOs with the same contents") { auto op1=util.build_struct(val1); + auto op2=util.build_struct(val1); - SECTION("same value") - { - INFO(val1.op0().type().id_string()); - - auto op2=util.build_struct(val1); - - REQUIRE(util.read_component(op1, b)==val1.op1()); - REQUIRE(util.read_component(op1, a)==val1.op0()); - - INFO(c.pretty()); - - const exprt &arr_val2=util.read_component(op1, c); - INFO(arr_val2.pretty()); - - REQUIRE(arr_val2==val1.op2()); - - REQUIRE(util.read_component(op2, a)==val1.op0()); - REQUIRE(util.read_component(op2, b)==val1.op1()); - REQUIRE(util.read_component(op2, c)==val1.op2()); - - result=abstract_objectt::merge(op1, op2, modified); + result=abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= - std::dynamic_pointer_cast( - result); + const auto &cast_result= + std::dynamic_pointer_cast( + result); + THEN("The original struct AO should be returned") + { // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); @@ -171,15 +154,20 @@ TEST_CASE("merge_full_struct_abstract_object", // Is optimal REQUIRE(result==op1); } - SECTION("different array") - { - abstract_object_pointert op2=util.build_struct(val2); + } + WHEN("Merging two constant struct AOs with the different contents") + { + auto op1=util.build_struct(val1); + auto op2=util.build_struct(val2); - result=abstract_objectt::merge(op1, op2, modified); + result=abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= - std::dynamic_pointer_cast( - result); + const auto &cast_result= + std::dynamic_pointer_cast( + result); + THEN("A new constant struct AO whose a component is the same and the " + "b and c are set to top") + { // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); From 430f93412073cb5024a0624be9ef7618f6e366f8 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 5 May 2017 18:29:11 +0100 Subject: [PATCH 122/129] Corrected guard on specialised merge --- .../variable-sensitivity/constant_array_abstract_object.cpp | 2 +- .../variable-sensitivity/full_struct_abstract_object.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 98ce974538b..daad845128f 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -133,7 +133,7 @@ Function: constant_array_abstract_objectt::constant_array_merge abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( const constant_array_abstract_object_pointert other) const { - if(is_top() || other->is_bottom()) + if(is_top() || other->is_bottom() || other->is_top()) { return array_abstract_objectt::merge(other); } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 49a6b36ee05..1ce106cb436 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -360,7 +360,7 @@ Function: full_struct_abstract_objectt::merge_constant_structs abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( constant_struct_pointert other) const { - if(is_top() || other->is_bottom()) + if(is_top() || other->is_bottom() || other->is_top()) { return struct_abstract_objectt::merge(other); } From 66561d7f23d45e2124333e2c783fc8cdcd850cf7 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 5 May 2017 18:29:33 +0100 Subject: [PATCH 123/129] Made pointer to array name consistent --- .../variable-sensitivity/constant_array_abstract_object.cpp | 2 +- .../variable-sensitivity/constant_array_abstract_object.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index daad845128f..c5943bb98b9 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -131,7 +131,7 @@ Function: constant_array_abstract_objectt::constant_array_merge \*******************************************************************/ abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( - const constant_array_abstract_object_pointert other) const + const constant_array_pointert other) const { if(is_top() || other->is_bottom() || other->is_top()) { diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index 7eb718788a9..24a8c87799e 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -21,7 +21,7 @@ class constant_array_abstract_objectt:public array_abstract_objectt { public: typedef sharing_ptrt const - constant_array_abstract_object_pointert; + constant_array_pointert; explicit constant_array_abstract_objectt(typet type); constant_array_abstract_objectt(typet type, bool top, bool bottom); @@ -71,7 +71,7 @@ class constant_array_abstract_objectt:public array_abstract_objectt const abstract_environmentt &env, const namespacet &ns) const; abstract_object_pointert constant_array_merge( - const constant_array_abstract_object_pointert other) const; + const constant_array_pointert other) const; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ARRAY_ABSTRACT_OBJECT_H From deba2a3d5e630260a3e935356e8905c8ac4b24d8 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 5 May 2017 18:29:49 +0100 Subject: [PATCH 124/129] Constant array reading from top handled correctly --- .../constant_array_abstract_object.cpp | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index c5943bb98b9..e1e7fb79aaa 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -225,26 +225,35 @@ abstract_object_pointert constant_array_abstract_objectt::read_index( const index_exprt &index, const namespacet &ns) const { - mp_integer index_value; - if(eval_index(index, env, ns, index_value)) + if(is_top()) { - // Here we are assuming it is always in bounds - if(map.find(index_value)==map.cend()) + return env.abstract_object_factory( + index.type(), ns, true); + } + else + { + assert(!is_bottom()); + mp_integer index_value; + if(eval_index(index, env, ns, index_value)) { - return env.abstract_object_factory(type().subtype(), ns, true, false); + // Here we are assuming it is always in bounds + if(map.find(index_value)==map.cend()) + { + return env.abstract_object_factory(type().subtype(), ns, true, false); + } + else + { + return map.find(index_value)->second; + } } else { - return map.find(index_value)->second; + // Reading from somewhere in the array + // TODO(tkiley): merge all the values of the array, we may be able to + // do better than returning top + return env.abstract_object_factory(type().subtype(), ns, true, false); } } - else - { - // Reading from somewhere in the array - // TODO(tkiley): merge all the values of the array, we may be able to - // do better than returning top - return env.abstract_object_factory(type().subtype(), ns, true, false); - } } /*******************************************************************\ From b1ac428c758a8f891d22dfe46b5062b43fb1abf3 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 5 May 2017 18:30:19 +0100 Subject: [PATCH 125/129] Completed test suite for full struct and constant array AOs --- .../constant_array_abstract_object/merge.cpp | 708 +++++++++++++++--- .../full_struct_abstract_object/merge.cpp | 530 ++++++++++++- 2 files changed, 1149 insertions(+), 89 deletions(-) diff --git a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp index b3d3ccdc1c8..13d5491bd0c 100644 --- a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp @@ -21,7 +21,7 @@ #include #include -typedef constant_array_abstract_objectt::constant_array_abstract_object_pointert +typedef constant_array_abstract_objectt::constant_array_pointert constant_array_abstract_object_pointert; // Util @@ -34,6 +34,27 @@ class array_utilt enviroment(enviroment), ns(ns) {} + constant_array_abstract_objectt::constant_array_pointert build_array( + const exprt &array_expr) + { + return std::make_shared( + array_expr, enviroment, ns); + } + + constant_array_abstract_objectt::constant_array_pointert build_top_array( + const typet &array_type) + { + return std::make_shared( + array_type, true, false); + } + + constant_array_abstract_objectt::constant_array_pointert build_bottom_array( + const typet &array_type) + { + return std::make_shared( + array_type, false, true); + } + exprt read_index( constant_array_abstract_object_pointert array_object, const index_exprt &index) const @@ -52,101 +73,620 @@ SCENARIO("merge_constant_array_abstract_object", { GIVEN("Two arrays of size 3, whose first elements are the same") { - // int val1[3] = {1, 2, 3} - exprt val1= - array_exprt( - array_typet(integer_typet(), constant_exprt::integer_constant(3))); - val1.operands().push_back(constant_exprt::integer_constant(1)); - val1.operands().push_back(constant_exprt::integer_constant(2)); - val1.operands().push_back(constant_exprt::integer_constant(3)); - - // int val2[3] = {1, 4, 5} - exprt val2= - array_exprt( - array_typet(integer_typet(), constant_exprt::integer_constant(3))); - val2.operands().push_back(constant_exprt::integer_constant(1)); - val2.operands().push_back(constant_exprt::integer_constant(4)); - val2.operands().push_back(constant_exprt::integer_constant(5)); - - // index_exprt for reading from an array - const index_exprt i0= - index_exprt(nil_exprt(), constant_exprt::integer_constant(0)); - const index_exprt i1= - index_exprt(nil_exprt(), constant_exprt::integer_constant(1)); - const index_exprt i2= - index_exprt(nil_exprt(), constant_exprt::integer_constant(2)); - - abstract_environmentt enviroment; - symbol_tablet symbol_table; - namespacet ns(symbol_table); - - optionst options; - options.set_option("pointers", true); - options.set_option("arrays", true); - options.set_option("structs", true); - variable_sensitivity_object_factoryt::instance().set_options(options); - - array_utilt util(enviroment, ns); - - abstract_object_pointert result; - bool modified=false; - WHEN("Merging two constant array AOs with the same array") - { - auto op1= - std::make_shared(val1, enviroment, ns); - auto op2= - std::make_shared(val1, enviroment, ns); + const array_typet array_type( + integer_typet(), constant_exprt::integer_constant(3)); + + // int val1[3] = {1, 2, 3} + exprt val1=array_exprt(array_type); + val1.operands().push_back(constant_exprt::integer_constant(1)); + val1.operands().push_back(constant_exprt::integer_constant(2)); + val1.operands().push_back(constant_exprt::integer_constant(3)); + + // int val2[3] = {1, 4, 5} + exprt val2=array_exprt(array_type); + val2.operands().push_back(constant_exprt::integer_constant(1)); + val2.operands().push_back(constant_exprt::integer_constant(4)); + val2.operands().push_back(constant_exprt::integer_constant(5)); + + // index_exprt for reading from an array + const index_exprt i0= + index_exprt(nil_exprt(), constant_exprt::integer_constant(0)); + const index_exprt i1= + index_exprt(nil_exprt(), constant_exprt::integer_constant(1)); + const index_exprt i2= + index_exprt(nil_exprt(), constant_exprt::integer_constant(2)); + + abstract_environmentt enviroment; + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + optionst options; + options.set_option("pointers", true); + options.set_option("arrays", true); + options.set_option("structs", true); + variable_sensitivity_object_factoryt::instance().set_options(options); + + array_utilt util(enviroment, ns); + + abstract_object_pointert result; + bool modified=false; + + WHEN("Merging two constant array AOs with the same array") + { + auto op1=util.build_array(val1); + auto op2=util.build_array(val1); - result=abstract_objectt::merge(op1, op2, modified); + result=abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= - std::dynamic_pointer_cast( - result); - THEN("The original constant array AO should be returned") + const auto &cast_result= + std::dynamic_pointer_cast( + result); + THEN("The original constant array AO should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==val1.op0()); + REQUIRE(util.read_index(cast_result, i1)==val1.op1()); + REQUIRE(util.read_index(cast_result, i2)==val1.op2()); + + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging two constant array AOs with different value arrays") { - // Though we may become top or bottom, the type should be unchanged - REQUIRE(cast_result); + auto op1=util.build_array(val1); + auto op2=util.build_array(val2); + + result=abstract_objectt::merge(op1, op2, modified); - // Correctness of merge - REQUIRE_FALSE(modified); - REQUIRE_FALSE(cast_result->is_top()); - REQUIRE_FALSE(cast_result->is_bottom()); - REQUIRE(util.read_index(cast_result, i0)==val1.op0()); - REQUIRE(util.read_index(cast_result, i1)==val1.op1()); - REQUIRE(util.read_index(cast_result, i2)==val1.op2()); + const auto &cast_result= + std::dynamic_pointer_cast( + result); - // Is optimal - REQUIRE(result==op1); + THEN("A new constant array AO whose first value is the same and " + "the other two are top") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==val1.op0()); + REQUIRE(util.read_index(cast_result, i1)==nil_exprt()); + REQUIRE(util.read_index(cast_result, i2)==nil_exprt()); + + // Since it has modified, we definitely shouldn't be reusing the pointer + REQUIRE_FALSE(result==op1); + } } - } - WHEN("Merging two constant array AOs with different value arrays") - { - auto op1= - std::make_shared(val1, enviroment, ns); - auto op2= - std::make_shared(val2, enviroment, ns); + WHEN("Merging a constant array AO with a value " + "with a constant array AO set to top") + { + auto op1=util.build_array(val1); + auto op2=util.build_top_array(array_type); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast( + result); + THEN("A new constant array AO set to top should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==nil_exprt()); + REQUIRE(util.read_index(cast_result, i1)==nil_exprt()); + REQUIRE(util.read_index(cast_result, i2)==nil_exprt()); + + // We can't reuse the abstract object as the value has changed + REQUIRE(result!=op1); + } + } + WHEN("Merging a constant array AO with a value " + "with a constant array AO set to bottom") + { + auto op1=util.build_array(val1); + auto op2=util.build_bottom_array(array_type); + + result=abstract_objectt::merge(op1, op2, modified); - result=abstract_objectt::merge(op1, op2, modified); + const auto &cast_result= + std::dynamic_pointer_cast( + result); + THEN("The original const AO should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); - const auto &cast_result= - std::dynamic_pointer_cast(result); + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==val1.op0()); + REQUIRE(util.read_index(cast_result, i1)==val1.op1()); + REQUIRE(util.read_index(cast_result, i2)==val1.op2()); - THEN("A new constant array AO whose first value is the same and " - "the other two are top") + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging a constant array AO set to top " + "with a constant array AO with a value") + { + auto op1=util.build_top_array(array_type); + auto op2=util.build_array(val1); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast( + result); + THEN("The original constant array AO should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==nil_exprt()); + REQUIRE(util.read_index(cast_result, i1)==nil_exprt()); + REQUIRE(util.read_index(cast_result, i2)==nil_exprt()); + + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging a constant array AO set to top " + "with a constant array AO set to top") + { + auto op1=util.build_top_array(array_type); + auto op2=util.build_top_array(array_type); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast( + result); + THEN("The original constant array AO should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==nil_exprt()); + REQUIRE(util.read_index(cast_result, i1)==nil_exprt()); + REQUIRE(util.read_index(cast_result, i2)==nil_exprt()); + + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging a constant array AO set to top " + "with a constant array AO set to bottom") + { + auto op1=util.build_top_array(array_type); + auto op2=util.build_bottom_array(array_type); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast( + result); + THEN("The original constant array AO should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==nil_exprt()); + REQUIRE(util.read_index(cast_result, i1)==nil_exprt()); + REQUIRE(util.read_index(cast_result, i2)==nil_exprt()); + + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging a constant array AO set to bottom " + "with a constant array AO with a value") { - // Though we may become top or bottom, the type should be unchanged - REQUIRE(cast_result); + auto op1=util.build_bottom_array(array_type); + auto op2=util.build_array(val1); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast( + result); + THEN("A new AO should be returned with op2s valuee") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==val1.op0()); + REQUIRE(util.read_index(cast_result, i1)==val1.op1()); + REQUIRE(util.read_index(cast_result, i2)==val1.op2()); + + // Is optimal + REQUIRE(result!=op1); + } + } + WHEN("Merging a constant array AO set to bottom " + "with a constant array AO set to top") + { + auto op1=util.build_bottom_array(array_type); + auto op2=util.build_top_array(array_type); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast( + result); + THEN("A new constant array AO should be returned set to top ") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==nil_exprt()); + REQUIRE(util.read_index(cast_result, i1)==nil_exprt()); + REQUIRE(util.read_index(cast_result, i2)==nil_exprt()); + + // Is optimal + REQUIRE(result!=op1); + } + } + WHEN("Merging a constant array AO set to bottom " + "with a constant array AO set to bottom") + { + auto op1=util.build_bottom_array(array_type); + auto op2=util.build_bottom_array(array_type); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast( + result); + THEN("The original bottom AO should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE(cast_result->is_bottom()); + + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging constant array AO with value " + "with a abstract object set to top") + { + const auto &op1=util.build_array(val1); + const auto &op2= + std::make_shared(val1.type(), true, false); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast( + result); + + THEN("We should get a new AO of the same type but set to top") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + + // Since it has modified, we definitely shouldn't be reusing the pointer + REQUIRE_FALSE(result==op1); + } + } + WHEN("Merging constant array AO with value " + "with a abstract object set to bottom") + { + const auto &op1=util.build_array(val1); + const auto &op2= + std::make_shared(val1.type(), false, true); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast( + result); + THEN("We should get the same constant array AO back") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_index(cast_result, i0)==val1.op0()); + REQUIRE(util.read_index(cast_result, i1)==val1.op1()); + REQUIRE(util.read_index(cast_result, i2)==val1.op2()); + + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging constant array AO set to top " + "with a abstract object set to top") + { + const auto &op1= + util.build_top_array(array_type); + const auto &op2= + std::make_shared(val1.type(), true, false); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + THEN("We should get the same abstract object back") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + + // Is type still correct + const auto &cast_result= + std::dynamic_pointer_cast( + result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + } + } + WHEN("Merging constant array AO set to top " + "with a abstract object set to bottom") + { + const auto &op1= + util.build_top_array(array_type); + const auto &op2= + std::make_shared(val1.type(), false, true); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("Should get the same abstract object back") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + + // Is type still correct + const auto &cast_result= + std::dynamic_pointer_cast( + result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + } + } + WHEN("Merging constant array AO set to bottom " + " with a abstract object set to top") + { + const auto &op1= + util.build_bottom_array(array_type); + const auto &op2= + std::make_shared(val1.type(), true, false); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("Return a new top abstract object of the same type") + { + // Simple correctness of merge + REQUIRE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // We don't optimize for returning the second parameter if we can + + // Is type still correct + const auto &cast_result= + std::dynamic_pointer_cast( + result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + } + } + WHEN("Merging constant array AO set to bottom with a AO set to bottom") + { + const auto &op1= + util.build_bottom_array(array_type); + const auto &op2= + std::make_shared(val1.type(), false, true); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("Return the original abstract object") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(result->is_top()); + REQUIRE(result->is_bottom()); + + // Optimization check + REQUIRE(result==op1); + + // Is type still correct + const auto &cast_result= + std::dynamic_pointer_cast( + result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + } + } + WHEN("Merging AO set to top with a constant array AO with a value") + { + const auto &op1= + std::make_shared(val1.type(), true, false); + const auto &op2=util.build_array(val1); + + bool modified; + + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("The original AO should be returned") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + } + } + WHEN("Merging AO set to top with a constant array AO set to top") + { + const auto &op1= + std::make_shared(val1.type(), true, false); + const auto &op2= + util.build_top_array(array_type); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("The original AO should be returned") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + } + } + WHEN("Merging AO set to top with a constant array AO set to bottom") + { + const auto &op1= + std::make_shared(val1.type(), true, false); + const auto &op2= + util.build_bottom_array(array_type); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("The original AO should be returned") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + } + } + WHEN("Merging AO set to bottom with a constant array AO with a value") + { + const auto &op1= + std::make_shared(val1.type(), false, true); + const auto &op2=util.build_array(val1); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + THEN("The a new top AO should be returned") + { + // Simple correctness of merge + REQUIRE(modified); + REQUIRE(typeid(result.get())==typeid(const abstract_objectt *)); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + } + + // We don't optimize for returning the second parameter if we can + } + WHEN("Merging AO set to bottom with a constant array AO set to top") + { + const auto &op1= + std::make_shared(val1.type(), false, true); + const auto &op2= + util.build_top_array(array_type); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + THEN("The a new top AO should be returned") + { + // Simple correctness of merge + REQUIRE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // We don't optimize for returning the second parameter if we can + } + } + WHEN("Merging AO set to bottom with a constant array AO set to bottom") + { + const auto &op1= + std::make_shared(val1.type(), false, true); + const auto &op2= + util.build_bottom_array(array_type); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); - // Correctness of merge - REQUIRE(modified); - REQUIRE_FALSE(cast_result->is_top()); - REQUIRE_FALSE(cast_result->is_bottom()); - REQUIRE(util.read_index(cast_result, i0)==val1.op0()); - REQUIRE(util.read_index(cast_result, i1)==nil_exprt()); - REQUIRE(util.read_index(cast_result, i2)==nil_exprt()); + THEN("The original AO should be returned") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(result->is_top()); + REQUIRE(result->is_bottom()); - // Since it has modified, we definitely shouldn't be reusing the pointer - REQUIRE_FALSE(result==op1); + REQUIRE(result==op1); } } } diff --git a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp index 868f47ccf7b..e2834a3ba7f 100644 --- a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp @@ -24,7 +24,7 @@ #include -typedef constant_array_abstract_objectt::constant_array_abstract_object_pointert +typedef constant_array_abstract_objectt::constant_array_pointert constant_array_abstract_object_pointert; // Util @@ -77,6 +77,20 @@ class struct_utilt return result; } + full_struct_abstract_objectt::constant_struct_pointert build_top_struct( + const typet &struct_type) + { + return std::make_shared( + struct_type, true, false); + } + + full_struct_abstract_objectt::constant_struct_pointert build_bottom_struct( + const typet &struct_type) + { + return std::make_shared( + struct_type, false, true); + } + private: abstract_environmentt &enviroment; const namespacet ns; @@ -136,8 +150,7 @@ SCENARIO("merge_full_struct_abstract_object", result=abstract_objectt::merge(op1, op2, modified); const auto &cast_result= - std::dynamic_pointer_cast( - result); + std::dynamic_pointer_cast(result); THEN("The original struct AO should be returned") { // Though we may become top or bottom, the type should be unchanged @@ -163,8 +176,7 @@ SCENARIO("merge_full_struct_abstract_object", result=abstract_objectt::merge(op1, op2, modified); const auto &cast_result= - std::dynamic_pointer_cast( - result); + std::dynamic_pointer_cast(result); THEN("A new constant struct AO whose a component is the same and the " "b and c are set to top") { @@ -184,5 +196,513 @@ SCENARIO("merge_full_struct_abstract_object", REQUIRE_FALSE(result==op1); } } + WHEN("Merging a constant struct AO with a value " + "with a constant struct AO set to top") + { + auto op1=util.build_struct(val1); + auto op2=util.build_top_struct(struct_type); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + THEN("A new constant struct AO set to top should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_component(cast_result, a)==nil_exprt()); + REQUIRE(util.read_component(cast_result, b)==nil_exprt()); + REQUIRE(util.read_component(cast_result, c)==nil_exprt()); + + // We can't reuse the abstract object as the value has changed + REQUIRE(result!=op1); + } + } + WHEN("Merging a constant struct AO with a value " + "with a constant struct AO set to bottom") + { + auto op1=util.build_struct(val1); + auto op2=util.build_bottom_struct(struct_type); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + THEN("The original const AO should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_component(cast_result, a)==val1.op0()); + REQUIRE(util.read_component(cast_result, b)==val1.op1()); + REQUIRE(util.read_component(cast_result, c)==val1.op2()); + + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging a constant struct AO set to top " + "with a constant struct AO with a value") + { + auto op1=util.build_top_struct(struct_type); + auto op2=util.build_struct(val1); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + THEN("The original constant struct AO should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_component(cast_result, a)==nil_exprt()); + REQUIRE(util.read_component(cast_result, b)==nil_exprt()); + REQUIRE(util.read_component(cast_result, c)==nil_exprt()); + + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging a constant struct AO set to top " + "with a constant struct AO set to top") + { + auto op1=util.build_top_struct(struct_type); + auto op2=util.build_top_struct(struct_type); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + THEN("The original constant struct AO should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_component(cast_result, a)==nil_exprt()); + REQUIRE(util.read_component(cast_result, b)==nil_exprt()); + REQUIRE(util.read_component(cast_result, c)==nil_exprt()); + + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging a constant struct AO set to top " + "with a constant struct AO set to bottom") + { + auto op1=util.build_top_struct(struct_type); + auto op2=util.build_bottom_struct(struct_type); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + THEN("The original constant struct AO should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_component(cast_result, a)==nil_exprt()); + REQUIRE(util.read_component(cast_result, b)==nil_exprt()); + REQUIRE(util.read_component(cast_result, c)==nil_exprt()); + + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging a constant struct AO set to bottom " + "with a constant struct AO with a value") + { + auto op1=util.build_bottom_struct(struct_type); + auto op2=util.build_struct(val1); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + THEN("A new AO should be returned with op2s valuee") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_component(cast_result, a)==val1.op0()); + REQUIRE(util.read_component(cast_result, b)==val1.op1()); + REQUIRE(util.read_component(cast_result, c)==val1.op2()); + + // Is optimal + REQUIRE(result!=op1); + } + } + WHEN("Merging a constant struct AO set to bottom " + "with a constant struct AO set to top") + { + auto op1=util.build_bottom_struct(struct_type); + auto op2=util.build_top_struct(struct_type); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + THEN("A new constant struct AO should be returned set to top ") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_component(cast_result, a)==nil_exprt()); + REQUIRE(util.read_component(cast_result, b)==nil_exprt()); + REQUIRE(util.read_component(cast_result, c)==nil_exprt()); + + // Is optimal + REQUIRE(result!=op1); + } + } + WHEN("Merging a constant struct AO set to bottom " + "with a constant struct AO set to bottom") + { + auto op1=util.build_bottom_struct(struct_type); + auto op2=util.build_bottom_struct(struct_type); + + result=abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + THEN("The original bottom AO should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE(cast_result->is_bottom()); + + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging constant struct AO with value " + "with a abstract object set to top") + { + const auto &op1=util.build_struct(val1); + const auto &op2= + std::make_shared(val1.type(), true, false); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + + THEN("We should get a new AO of the same type but set to top") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE(modified); + REQUIRE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + + // Since it has modified, we definitely shouldn't be reusing the pointer + REQUIRE_FALSE(result==op1); + } + } + WHEN("Merging constant struct AO with value " + "with a abstract object set to bottom") + { + const auto &op1=util.build_struct(val1); + const auto &op2= + std::make_shared(val1.type(), false, true); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + const auto &cast_result= + std::dynamic_pointer_cast(result); + THEN("We should get the same constant struct AO back") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(util.read_component(cast_result, a)==val1.op0()); + REQUIRE(util.read_component(cast_result, b)==val1.op1()); + REQUIRE(util.read_component(cast_result, c)==val1.op2()); + + // Is optimal + REQUIRE(result==op1); + } + } + WHEN("Merging constant struct AO set to top " + "with a abstract object set to top") + { + const auto &op1= + util.build_top_struct(struct_type); + const auto &op2= + std::make_shared(val1.type(), true, false); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + THEN("We should get the same abstract object back") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + + // Is type still correct + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + } + } + WHEN("Merging constant struct AO set to top " + "with a abstract object set to bottom") + { + const auto &op1= + util.build_top_struct(struct_type); + const auto &op2= + std::make_shared(val1.type(), false, true); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("Should get the same abstract object back") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + + // Is type still correct + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + } + } + WHEN("Merging constant struct AO set to bottom " + " with a abstract object set to top") + { + const auto &op1= + util.build_bottom_struct(struct_type); + const auto &op2= + std::make_shared(val1.type(), true, false); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("Return a new top abstract object of the same type") + { + // Simple correctness of merge + REQUIRE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // We don't optimize for returning the second parameter if we can + + // Is type still correct + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + } + } + WHEN("Merging constant struct AO set to bottom with a AO set to bottom") + { + const auto &op1= + util.build_bottom_struct(struct_type); + const auto &op2= + std::make_shared(val1.type(), false, true); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("Return the original abstract object") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(result->is_top()); + REQUIRE(result->is_bottom()); + + // Optimization check + REQUIRE(result==op1); + + // Is type still correct + const auto &cast_result= + std::dynamic_pointer_cast(result); + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + } + } + WHEN("Merging AO set to top with a constant struct AO with a value") + { + const auto &op1= + std::make_shared(val1.type(), true, false); + const auto &op2=util.build_struct(val1); + + bool modified; + + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("The original AO should be returned") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + } + } + WHEN("Merging AO set to top with a constant struct AO set to top") + { + const auto &op1= + std::make_shared(val1.type(), true, false); + const auto &op2= + util.build_top_struct(struct_type); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("The original AO should be returned") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + } + } + WHEN("Merging AO set to top with a constant struct AO set to bottom") + { + const auto &op1= + std::make_shared(val1.type(), true, false); + const auto &op2= + util.build_bottom_struct(struct_type); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + THEN("The original AO should be returned") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // Is optimal + REQUIRE(op1==result); + } + } + WHEN("Merging AO set to bottom with a constant struct AO with a value") + { + const auto &op1= + std::make_shared(val1.type(), false, true); + const auto &op2=util.build_struct(val1); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + THEN("The a new top AO should be returned") + { + // Simple correctness of merge + REQUIRE(modified); + REQUIRE(typeid(result.get())==typeid(const abstract_objectt *)); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + } + + // We don't optimize for returning the second parameter if we can + } + WHEN("Merging AO set to bottom with a constant struct AO set to top") + { + const auto &op1= + std::make_shared(val1.type(), false, true); + const auto &op2= + util.build_top_struct(struct_type); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + THEN("The a new top AO should be returned") + { + // Simple correctness of merge + REQUIRE(modified); + REQUIRE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + + // We don't optimize for returning the second parameter if we can + } + } + WHEN("Merging AO set to bottom with a constant struct AO set to bottom") + { + const auto &op1= + std::make_shared(val1.type(), false, true); + const auto &op2= + util.build_bottom_struct(struct_type); + + bool modified; + abstract_object_pointert result= + abstract_objectt::merge(op1, op2, modified); + + THEN("The original AO should be returned") + { + // Simple correctness of merge + REQUIRE_FALSE(modified); + REQUIRE_FALSE(result->is_top()); + REQUIRE(result->is_bottom()); + + REQUIRE(result==op1); + } + } } } From d4afa61b16ddca0effa8aa4505396fc083194adc Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 9 May 2017 12:29:46 +0100 Subject: [PATCH 126/129] Correctly set up the enviroment before running tests In release builds, the top/bottom status of the enviroment was undefined. This ensures the enviroment is set to top (i.e. an entry point). --- .../variable-sensitivity/constant_abstract_value/merge.cpp | 1 + .../constant_array_abstract_object/merge.cpp | 1 + .../variable-sensitivity/full_struct_abstract_object/merge.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp index 5572eaa33e0..3191ee9d132 100644 --- a/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp @@ -32,6 +32,7 @@ SCENARIO("merge_constant_abstract_value", const exprt val2=constant_exprt::integer_constant(2); abstract_environmentt enviroment; + enviroment.make_top(); symbol_tablet symbol_table; namespacet ns(symbol_table); diff --git a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp index 13d5491bd0c..964084489a6 100644 --- a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp @@ -97,6 +97,7 @@ SCENARIO("merge_constant_array_abstract_object", index_exprt(nil_exprt(), constant_exprt::integer_constant(2)); abstract_environmentt enviroment; + enviroment.make_top(); symbol_tablet symbol_table; namespacet ns(symbol_table); diff --git a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp index e2834a3ba7f..7c888c38421 100644 --- a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp @@ -128,6 +128,7 @@ SCENARIO("merge_full_struct_abstract_object", const member_exprt c(nil_exprt(), "c"); abstract_environmentt enviroment; + enviroment.make_top(); symbol_tablet symbol_table; namespacet ns(symbol_table); From f7f3db0fc488fe02befb673edf585c250aabd490 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 11 May 2017 11:36:14 +0100 Subject: [PATCH 127/129] Extracted out logic for when to use a 2 value merge Previously each abstract object that implemented merge had to correctly redirect merging top with anything or merging with a bottom. This is now handled directly in the root merge by checking the three cases where the base merge must be used. If this is bottom must still be handled by derived classes as we must create an abstract object of the same type. --- .../variable-sensitivity/abstract_object.cpp | 44 ++++++++++++++++++- .../variable-sensitivity/abstract_object.h | 5 +++ .../constant_abstract_value.cpp | 6 +-- .../constant_array_abstract_object.cpp | 6 +-- .../constant_pointer_abstract_object.cpp | 6 +-- .../full_struct_abstract_object.cpp | 6 +-- 6 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 2f59ec2219a..15b21f6c27a 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -112,6 +112,26 @@ Function: abstract_objectt::merge abstract_object_pointert abstract_objectt::merge( abstract_object_pointert other) const +{ + return abstract_object_merge(other); +} + +/*******************************************************************\ + +Function: abstract_objectt::abstract_object_merge + + Inputs: + other - The object to merge with this + + Outputs: Returns the result of the abstract object. + + Purpose: Create a new abstract object that is the result of the merge, unless + the object would be unchanged, then would return itself. + +\*******************************************************************/ + +abstract_object_pointert abstract_objectt::abstract_object_merge( + const abstract_object_pointert other) const { if(top) return shared_from_this(); @@ -125,7 +145,6 @@ abstract_object_pointert abstract_objectt::merge( return merged; } - /*******************************************************************\ Function: abstract_objectt::expression_transform @@ -286,10 +305,31 @@ abstract_object_pointert abstract_objectt::merge( abstract_object_pointert op2, bool &out_modifications) { - abstract_object_pointert result=op1->merge(op2); + abstract_object_pointert result=op1->should_use_base_merge(op2)? + op1->abstract_object_merge(op2):op1->merge(op2); // If no modifications, we will return the original pointer out_modifications=result!=op1; return result; } +/*******************************************************************\ + +Function: abstract_objectt::should_use_base_merge + + Inputs: + other - the object being merged with + + Outputs: Returns true if the base class is capable of doing a complete merge + + Purpose: To detect the cases where the base merge is sufficient to do a merge + We can't do if this->is_bottom() since we want the specific + +\*******************************************************************/ + +bool abstract_objectt::should_use_base_merge( + const abstract_object_pointert other) const +{ + return is_top() || other->is_bottom() || other->is_top(); +} + diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 9b6d12f0588..4eaf850d472 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -112,6 +112,9 @@ class abstract_objectt:public std::enable_shared_from_this // To enforce copy-on-write these are private and have read-only accessors typet t; bool bottom; + + abstract_object_pointert abstract_object_merge( + const abstract_object_pointert other) const; protected: template using internal_sharing_ptrt=std::shared_ptr; @@ -130,6 +133,8 @@ class abstract_objectt:public std::enable_shared_from_this // The one exception is merge in descendant classes, which needs this void make_top() { top=true; } + bool should_use_base_merge(const abstract_object_pointert other) const; + // Sets the state of this object virtual abstract_object_pointert merge(abstract_object_pointert other) const; diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index b38af463151..53ce145f3cd 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -101,11 +101,7 @@ Function: constant_abstract_valuet::merge_constant_constant abstract_object_pointert constant_abstract_valuet::merge_constant_constant( constant_abstract_value_pointert other) const { - if(is_top() || other->is_bottom()) - { - return abstract_valuet::merge(other); - } - else if(is_bottom()) + if(is_bottom()) { return std::make_shared(*other); } diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index e1e7fb79aaa..c9b427e3eb1 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -133,11 +133,7 @@ Function: constant_array_abstract_objectt::constant_array_merge abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( const constant_array_pointert other) const { - if(is_top() || other->is_bottom() || other->is_top()) - { - return array_abstract_objectt::merge(other); - } - else if(is_bottom()) + if(is_bottom()) { return std::make_shared(*other); } diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index e3f4ad2ea4c..f4590b9ed94 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -168,11 +168,7 @@ abstract_object_pointert constant_pointer_abstract_objectt::merge_constant_pointers( const constant_pointer_abstract_pointert other) const { - if(is_top() || other->is_bottom()) - { - return pointer_abstract_objectt::merge(other); - } - else if(is_bottom()) + if(is_bottom()) { return std::make_shared(*other); } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 1ce106cb436..466816e468f 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -360,11 +360,7 @@ Function: full_struct_abstract_objectt::merge_constant_structs abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( constant_struct_pointert other) const { - if(is_top() || other->is_bottom() || other->is_top()) - { - return struct_abstract_objectt::merge(other); - } - else if(is_bottom()) + if(is_bottom()) { return std::make_shared(*other); } From bb4f3788e1d8379ec77906b3b2d657327209d1e9 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 16 May 2017 17:14:34 +0100 Subject: [PATCH 128/129] Improved comment in the LHS simplify --- .../variable-sensitivity/variable_sensitivity_domain.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 7b726e36492..d46946b09f9 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -377,7 +377,9 @@ bool variable_sensitivity_domaint::ai_simplify_lhs( { member_exprt me = to_member_expr(condition); exprt compound = me.compound(); - bool changed = ai_simplify(compound, ns, true); // <-- true! + // Carry on the RHS since we still require an addressable object for the + // struct + bool changed = ai_simplify(compound, ns, true); if(changed) { me.compound() = compound; From 8601e81442dc69d9743e5e5dfa0961d8122f15bd Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 15 Jun 2017 17:52:41 +0100 Subject: [PATCH 129/129] Fixed ai_simplify in variable sensitivity domain to use new interface At some point this commit needs backdating as the ai_domain interface has changed under our feet. --- .../variable_sensitivity_domain.cpp | 31 +++++++------------ .../variable_sensitivity_domain.h | 7 ++--- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index d46946b09f9..6832d635055 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -270,25 +270,18 @@ Function: variable_sensitivity_domaint::ai_simplify \*******************************************************************/ bool variable_sensitivity_domaint::ai_simplify( - exprt &condition, const namespacet &ns, const bool lhs) const + exprt &condition, const namespacet &ns) const { - if(lhs) - { - return ai_simplify_lhs(condition, ns); - } + sharing_ptrt res=abstract_state.eval(condition, ns); + exprt c=res->to_constant(); + + if(c.id()==ID_nil) // TODO : simplification within an expression + return true; else { - sharing_ptrt res=abstract_state.eval(condition, ns); - exprt c=res->to_constant(); - - if(c.id()==ID_nil) // TODO : simplification within an expression - return true; - else - { - bool condition_changed=(condition!=c); - condition=c; - return !condition_changed; - } + bool condition_changed=(condition!=c); + condition=c; + return !condition_changed; } } @@ -351,7 +344,7 @@ bool variable_sensitivity_domaint::ai_simplify_lhs( { index_exprt ie = to_index_expr(condition); exprt index = ie.index(); - bool changed = ai_simplify(index, ns, false); + bool changed = ai_simplify(index, ns); if(changed) { ie.index() = index; @@ -364,7 +357,7 @@ bool variable_sensitivity_domaint::ai_simplify_lhs( { dereference_exprt de = to_dereference_expr(condition); exprt pointer = de.pointer(); - bool changed = ai_simplify(pointer, ns, false); + bool changed = ai_simplify(pointer, ns); if(changed) { de.pointer() = pointer; @@ -379,7 +372,7 @@ bool variable_sensitivity_domaint::ai_simplify_lhs( exprt compound = me.compound(); // Carry on the RHS since we still require an addressable object for the // struct - bool changed = ai_simplify(compound, ns, true); + bool changed = ai_simplify_lhs(compound, ns); if(changed) { me.compound() = compound; diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index de12a3f52bd..2e685c527cf 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -99,17 +99,16 @@ class variable_sensitivity_domaint:public ai_domain_baset bool ai_simplify( exprt &condition, - const namespacet &ns, - const bool lhs=false) const override; + const namespacet &ns) const override; bool is_bottom() const override; bool is_top() const override; -private: bool ai_simplify_lhs( exprt &condition, - const namespacet &ns) const; + const namespacet &ns) const override; +private: abstract_environmentt abstract_state; };