From bd17b0202a49975878c3f9f33655c9016b679862 Mon Sep 17 00:00:00 2001 From: martin Date: Sat, 7 Dec 2019 20:59:23 +0000 Subject: [PATCH 001/342] Use sharing_mapt for abstract environment --- src/util/sharing_map.h | 6 ++++++ src/util/std_expr.h | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/util/sharing_map.h b/src/util/sharing_map.h index 256fa24e8db..0c0042cbdb0 100644 --- a/src/util/sharing_map.h +++ b/src/util/sharing_map.h @@ -414,6 +414,12 @@ class sharing_mapt /// /// \param [out] view: Empty view void get_view(viewt &view) const; + viewt get_view() const + { + viewt result; + get_view(result); + return result; + } /// Get a delta view of the elements in the map /// diff --git a/src/util/std_expr.h b/src/util/std_expr.h index cb36b59912e..6f74c56a62e 100644 --- a/src/util/std_expr.h +++ b/src/util/std_expr.h @@ -114,6 +114,16 @@ class symbol_exprt : public nullary_exprt } }; +namespace std { + template<> struct hash<::symbol_exprt> + { + size_t operator()(const ::symbol_exprt& sym) + { + return irep_id_hash()(sym.get_identifier()); + } + }; +} + /// Expression to hold a symbol (variable) with extra accessors to /// ID_c_static_lifetime and ID_C_thread_local class decorated_symbol_exprt:public symbol_exprt From ca0f9f3af133fb8b9db26fafd7345e49c052b6d7 Mon Sep 17 00:00:00 2001 From: martin Date: Sat, 7 Dec 2019 21:00:15 +0000 Subject: [PATCH 002/342] Use sharing_mapt in constant_array_abstract_objectt --- src/util/sharing_map.h | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/util/sharing_map.h b/src/util/sharing_map.h index 0c0042cbdb0..b9ee5e74715 100644 --- a/src/util/sharing_map.h +++ b/src/util/sharing_map.h @@ -26,6 +26,7 @@ Author: Daniel Poetzl #include #include #include +#include #include "as_const.h" #include "irep.h" @@ -54,6 +55,11 @@ Author: Daniel Poetzl typename equalT> \ type sharing_mapt +#define SHARING_MAPTV(R, V) \ + template \ + template \ + R sharing_mapt + /// Macro to abbreviate the out-of-class definitions of methods of sharing_mapt /// with a return type that is defined within the class. /// @@ -363,6 +369,17 @@ class sharing_mapt /// View of the key-value pairs in the map. A view is a list of pairs with /// the components being const references to the keys and values in the map. typedef std::vector viewt; + typedef std::set sorted_viewt; + + static void insert_view_item(viewt &v, view_itemt &&vi) + { + v.push_back(vi); + } + + static void insert_view_item(sorted_viewt &v, view_itemt &&vi) + { + v.insert(vi); + } class delta_view_itemt { @@ -413,7 +430,7 @@ class sharing_mapt /// - Best case: O(N + H) /// /// \param [out] view: Empty view - void get_view(viewt &view) const; + template void get_view(V&) const; viewt get_view() const { viewt result; @@ -459,6 +476,9 @@ class sharing_mapt delta_viewt &delta_view, const bool only_common = true) const; + delta_viewt get_delta_view( + const sharing_mapt &other, const bool only_common=true) const; + /// Call a function for every key-value pair in the map. /// /// Complexity: as \ref sharing_mapt::get_view @@ -785,7 +805,7 @@ ::get_sharing_stats_map(Iterator begin, Iterator end) } #endif -SHARING_MAPT(void)::get_view(viewt &view) const +SHARING_MAPTV(void, view_type)::get_view(view_type &view) const { SM_ASSERT(view.empty()); @@ -793,7 +813,7 @@ SHARING_MAPT(void)::get_view(viewt &view) const return; auto f = [&view](const key_type &k, const mapped_type &m) { - view.push_back(view_itemt(k, m)); + insert_view_item(view, view_itemt(k, m)); }; iterate(map, f); @@ -1068,6 +1088,15 @@ ::get_delta_view( while(!stack.empty()); } +SHARING_MAPT2(, delta_viewt)::get_delta_view( + const sharing_mapt &other, + const bool only_common) const +{ + delta_viewt delta_view; + get_delta_view(other, delta_view, only_common); + return delta_view; +} + SHARING_MAPT2(, nodet &)::get_leaf_node(const key_type &k) { SM_ASSERT(has_key(k)); From 307c5694ac020128c3a55213accbdab026c005de Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 10:58:43 +0000 Subject: [PATCH 003/342] Fix various things that were broken with USE_STD_STRING In particular, this applies to the --vs-progress-string-statistics feature as this requires the string_container to be available. Other than that, there are also two places in the unit tests (which don't show up on travis because the unit tests are currently not being built on Travis if USE_STD_STRING is set) --- unit/util/sharing_map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unit/util/sharing_map.cpp b/unit/util/sharing_map.cpp index 41cefc9aedb..61ebac21c35 100644 --- a/unit/util/sharing_map.cpp +++ b/unit/util/sharing_map.cpp @@ -492,7 +492,7 @@ TEST_CASE("Sharing map views and iteration", "[core][util]") SECTION("View") { - typedef std::pair pt; + typedef std::pair pt; sharing_map_standardt sm; sharing_map_standardt::viewt view; From 5f51c5d1e9d31197cfa6e6cbf406ff997ba3562c Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 11 Oct 2019 15:35:01 +0100 Subject: [PATCH 004/342] Fixup sharing_map.h --- src/util/sharing_map.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/util/sharing_map.h b/src/util/sharing_map.h index b9ee5e74715..a0ba810b4a5 100644 --- a/src/util/sharing_map.h +++ b/src/util/sharing_map.h @@ -55,10 +55,15 @@ Author: Daniel Poetzl typename equalT> \ type sharing_mapt -#define SHARING_MAPTV(R, V) \ - template \ +#define SHARING_MAPTV(return_type, V) \ + template < \ + typename keyT, \ + typename valueT, \ + bool fail_if_equal, \ + typename hashT, \ + typename equalT> \ template \ - R sharing_mapt + return_type sharing_mapt /// Macro to abbreviate the out-of-class definitions of methods of sharing_mapt /// with a return type that is defined within the class. From 942f0fecd6bb021a8d4dcfc3da457c4ae73319e9 Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 11:07:36 +0000 Subject: [PATCH 005/342] Fixups post-rebase --- src/util/sharing_map.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/util/sharing_map.h b/src/util/sharing_map.h index a0ba810b4a5..52d97fc3fdb 100644 --- a/src/util/sharing_map.h +++ b/src/util/sharing_map.h @@ -289,6 +289,19 @@ class sharing_mapt template void insert(const key_type &k, valueU &&m); + template + void insert_or_replace(const key_type &k, valueU &&m) + { + if(has_key(k)) + { + replace(k, std::forward(m)); + } + else + { + insert(k, std::forward(m)); + } + } + /// Replace element, element must exist in map /// /// Complexity: From 17f2c3fa8f91ae2d09d7698d0cc756f7cb65815e Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 9 Dec 2019 22:17:10 +0000 Subject: [PATCH 006/342] Clang-format changes to the sharing map. --- src/util/sharing_map.h | 11 ++++++----- src/util/std_expr.h | 18 ++++++++++-------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/util/sharing_map.h b/src/util/sharing_map.h index 52d97fc3fdb..770ddafd794 100644 --- a/src/util/sharing_map.h +++ b/src/util/sharing_map.h @@ -26,7 +26,6 @@ Author: Daniel Poetzl #include #include #include -#include #include "as_const.h" #include "irep.h" @@ -391,12 +390,12 @@ class sharing_mapt static void insert_view_item(viewt &v, view_itemt &&vi) { - v.push_back(vi); + v.push_back(vi); } static void insert_view_item(sorted_viewt &v, view_itemt &&vi) { - v.insert(vi); + v.insert(vi); } class delta_view_itemt @@ -448,7 +447,8 @@ class sharing_mapt /// - Best case: O(N + H) /// /// \param [out] view: Empty view - template void get_view(V&) const; + template + void get_view(V &) const; viewt get_view() const { viewt result; @@ -495,7 +495,8 @@ class sharing_mapt const bool only_common = true) const; delta_viewt get_delta_view( - const sharing_mapt &other, const bool only_common=true) const; + const sharing_mapt &other, + const bool only_common = true) const; /// Call a function for every key-value pair in the map. /// diff --git a/src/util/std_expr.h b/src/util/std_expr.h index 6f74c56a62e..03e6671631f 100644 --- a/src/util/std_expr.h +++ b/src/util/std_expr.h @@ -114,15 +114,17 @@ class symbol_exprt : public nullary_exprt } }; -namespace std { - template<> struct hash<::symbol_exprt> +namespace std +{ +template <> +struct hash<::symbol_exprt> +{ + size_t operator()(const ::symbol_exprt &sym) { - size_t operator()(const ::symbol_exprt& sym) - { - return irep_id_hash()(sym.get_identifier()); - } - }; -} + return irep_id_hash()(sym.get_identifier()); + } +}; +} // namespace std /// Expression to hold a symbol (variable) with extra accessors to /// ID_c_static_lifetime and ID_C_thread_local From 764039ad3d5ea7312663718a8b81342c472b9acf Mon Sep 17 00:00:00 2001 From: martin Date: Fri, 3 Jul 2020 23:10:32 +0100 Subject: [PATCH 007/342] Various miscellaneous fixes Most of these are needed to make clang-format happy, or the linter, or to make it compile on Windows --- src/util/sharing_map.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/sharing_map.h b/src/util/sharing_map.h index 770ddafd794..c8d79b1ec72 100644 --- a/src/util/sharing_map.h +++ b/src/util/sharing_map.h @@ -448,7 +448,7 @@ class sharing_mapt /// /// \param [out] view: Empty view template - void get_view(V &) const; + void get_view(V &view) const; viewt get_view() const { viewt result; From 851e0175a2255b164a6211e691eeb2709d2cee72 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Mon, 2 Jul 2018 14:32:00 +0100 Subject: [PATCH 008/342] Add helper class for displaying memory quantities --- src/util/Makefile | 1 + src/util/memory_units.cpp | 115 ++++++++++++++++++++++++++++++++++++++ src/util/memory_units.h | 46 +++++++++++++++ 3 files changed, 162 insertions(+) create mode 100644 src/util/memory_units.cpp create mode 100644 src/util/memory_units.h diff --git a/src/util/Makefile b/src/util/Makefile index 8e800b92ded..d50c5b54322 100644 --- a/src/util/Makefile +++ b/src/util/Makefile @@ -46,6 +46,7 @@ SRC = allocate_objects.cpp \ mathematical_expr.cpp \ mathematical_types.cpp \ memory_info.cpp \ + memory_units.cpp \ merge_irep.cpp \ message.cpp \ mp_arith.cpp \ diff --git a/src/util/memory_units.cpp b/src/util/memory_units.cpp new file mode 100644 index 00000000000..901541d0536 --- /dev/null +++ b/src/util/memory_units.cpp @@ -0,0 +1,115 @@ +/*******************************************************************\ + +Module: Memory units + +Author: Hannes Steffenhagen + +\*******************************************************************/ + +#include "memory_units.h" + +#include + +memory_sizet::memory_sizet() : bytes(0) +{ +} +memory_sizet::memory_sizet(std::size_t bytes) : bytes(bytes) +{ +} +memory_sizet::memory_sizet(const memory_sizet &other) : bytes(other.bytes) +{ +} +memory_sizet::memory_sizet(memory_sizet &&other) : bytes(other.bytes) +{ +} + +memory_sizet &memory_sizet::operator=(const memory_sizet &other) +{ + bytes = other.bytes; + return *this; +} + +memory_sizet &memory_sizet::operator=(memory_sizet &&other) noexcept +{ + bytes = other.bytes; + return *this; +} + +memory_sizet memory_sizet::from_bytes(std::size_t bytes) +{ + return memory_sizet(bytes); +} + +std::size_t memory_sizet::get_bytes() const +{ + return bytes; +} + +std::size_t memory_sizet::get_kibibytes() const +{ + return bytes / 1024; +} + +std::size_t memory_sizet::get_mebibytes() const +{ + return bytes / (1024 * 1024); +} + +std::size_t memory_sizet::get_gibibytes() const +{ + return bytes / (1024 * 1024 * 1024); +} + +std::string memory_sizet::to_string() const +{ + std::size_t remainder = get_bytes(); + std::ostringstream out; + const std::size_t gib = remainder / (1024 * 1024 * 1024); + remainder -= gib * 1024 * 1024 * 1024; + if(gib > 0) + { + out << gib << si_gibibyte_symbol; + } + const std::size_t mib = remainder / (1024 * 1024); + remainder -= mib * 1024 * 1024; + if(mib > 0) + { + if(gib > 0) + { + out << ' '; + } + out << mib << si_mebibyte_symbol; + } + const std::size_t kib = remainder / 1024; + remainder -= kib * 1024; + if(kib > 0) + { + if(mib > 0 || gib > 0) + { + out << ' '; + } + out << kib << si_kibibyte_symbol; + } + if(gib > 0 || mib > 0 || kib > 0) + { + out << ' '; + } + out << remainder << si_byte_symbol; + return out.str(); +} + +const char *memory_sizet::si_byte_symbol = "B"; +const char *memory_sizet::si_kibibyte_symbol = "KiB"; +const char *memory_sizet::si_mebibyte_symbol = "MiB"; +const char *memory_sizet::si_gibibyte_symbol = "GiB"; + +memory_sizet &memory_sizet::operator+=(const memory_sizet &other) +{ + bytes += other.bytes; + return *this; +} + +memory_sizet memory_sizet::operator+(const memory_sizet &other) const +{ + return memory_sizet(*this) += other; +} diff --git a/src/util/memory_units.h b/src/util/memory_units.h new file mode 100644 index 00000000000..f536c6fd993 --- /dev/null +++ b/src/util/memory_units.h @@ -0,0 +1,46 @@ +/*******************************************************************\ + +Module: Memory units + +Author: Hannes Steffenhagen + +\*******************************************************************/ + +#ifndef CPROVER_UTIL_MEMORY_UNITS_H +#define CPROVER_UTIL_MEMORY_UNITS_H + +#include +#include + +class memory_sizet +{ +public: + static memory_sizet from_bytes(std::size_t bytes); + + memory_sizet(); + memory_sizet(const memory_sizet &); + memory_sizet(memory_sizet &&); + + memory_sizet &operator=(const memory_sizet &); + memory_sizet &operator=(memory_sizet &&) noexcept; + + memory_sizet &operator+=(const memory_sizet &); + memory_sizet operator+(const memory_sizet &) const; + + std::size_t get_bytes() const; + std::size_t get_kibibytes() const; + std::size_t get_mebibytes() const; + std::size_t get_gibibytes() const; + std::string to_string() const; + + static const char *si_byte_symbol; + static const char *si_kibibyte_symbol; + static const char *si_mebibyte_symbol; + static const char *si_gibibyte_symbol; + +private: + std::size_t bytes; + explicit memory_sizet(std::size_t bytes); +}; + +#endif // CPROVER_UTIL_MEMORY_UNITS_H From d318f6fb40ec500ecdd7b945f55cfc7db0d1df6f Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Mon, 2 Jul 2018 14:32:30 +0100 Subject: [PATCH 009/342] Add helper for showing memory usage of string container --- src/util/string_container.cpp | 35 +++++++++++++++++++++++++++++++++++ src/util/string_container.h | 18 ++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/util/string_container.cpp b/src/util/string_container.cpp index 262634af190..bc81c861409 100644 --- a/src/util/string_container.cpp +++ b/src/util/string_container.cpp @@ -12,6 +12,8 @@ Author: Daniel Kroening, kroening@kroening.com #include "string_container.h" #include +#include +#include string_ptrt::string_ptrt(const char *_s):s(_s), len(strlen(_s)) { @@ -74,3 +76,36 @@ unsigned string_containert::get(const std::string &s) return r; } + +void string_container_statisticst::dump_on_stream(std::ostream &out) const +{ + auto total_memory_usage = strings_memory_usage + vector_memory_usage + + map_memory_usage + list_memory_usage; + out << "String container statistics:" + << "\n string count: " << string_count + << "\n string memory usage: " << strings_memory_usage.to_string() + << "\n vector memory usage: " << vector_memory_usage.to_string() + << "\n map memory usage: " << map_memory_usage.to_string() + << "\n list memory usage: " << list_memory_usage.to_string() + << "\n total memory usage: " << total_memory_usage.to_string() << '\n'; +} + +string_container_statisticst string_containert::compute_statistics() const +{ + string_container_statisticst result; + result.string_count = string_vector.size(); + result.vector_memory_usage = memory_sizet::from_bytes( + sizeof(string_vector) + + sizeof(string_vectort::value_type) * string_vector.capacity()); + result.strings_memory_usage = memory_sizet::from_bytes(std::accumulate( + begin(string_vector), + end(string_vector), + std::size_t(0), + [](std::size_t sz, const std::string *s) { return sz + s->capacity(); })); + result.map_memory_usage = memory_sizet::from_bytes( + sizeof(hash_table) + hash_table.size() * sizeof(hash_tablet::value_type)); + + result.list_memory_usage = memory_sizet::from_bytes( + sizeof(string_list) + 2 * sizeof(void *) * string_list.size()); + return result; +} diff --git a/src/util/string_container.h b/src/util/string_container.h index b63cb38905e..10d2ea4d3e6 100644 --- a/src/util/string_container.h +++ b/src/util/string_container.h @@ -16,6 +16,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include "memory_units.h" #include "string_hash.h" struct string_ptrt @@ -44,6 +45,21 @@ class string_ptr_hash size_t operator()(const string_ptrt s) const { return hash_string(s.s); } }; +/// Has estimated statistics about string container +/// (estimated because this only uses public information, +/// which disregards any internal control structures that +/// might be in use) +struct string_container_statisticst +{ + std::size_t string_count; + memory_sizet strings_memory_usage; + memory_sizet vector_memory_usage; + memory_sizet map_memory_usage; + memory_sizet list_memory_usage; + + void dump_on_stream(std::ostream &out) const; +}; + class string_containert { public: @@ -73,6 +89,8 @@ class string_containert return *string_vector[no]; } + string_container_statisticst compute_statistics() const; + protected: // the 'unsigned' ought to be size_t typedef std::unordered_map From 510b1c9bacc04cdc7fe46c0d963fdce1ad7dd91e Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 16 Oct 2017 14:54:21 +0100 Subject: [PATCH 010/342] Re-enable regression test that requires the variable senitivity domain. --- .../goto-analyzer/sensitivity-function-call-recursive/test.desc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regression/goto-analyzer/sensitivity-function-call-recursive/test.desc b/regression/goto-analyzer/sensitivity-function-call-recursive/test.desc index 6303fef7078..2bb1b2580e8 100644 --- a/regression/goto-analyzer/sensitivity-function-call-recursive/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-recursive/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE main.c --variable --pointers --arrays --structs --verify ^EXIT=0$ From a386b8e9cedd7da554ad3ba1999e558f7349c25f Mon Sep 17 00:00:00 2001 From: martin Date: Thu, 30 Nov 2017 18:58:51 +0000 Subject: [PATCH 011/342] Test cases for unreachable assertions. --- .../unreachable_assertions_01/main.c | 28 +++++++++++++++++++ .../unreachable_assertions_01/test.desc | 12 ++++++++ 2 files changed, 40 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 From 2a9c782fce4987e56fba1cef0cb6d58f475f6630 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 14 Feb 2017 18:08:37 +0000 Subject: [PATCH 012/342] 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 +++ 7 files changed, 1158 insertions(+) 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 510ab7646cd..67519286156 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -33,6 +33,9 @@ SRC = ai.cpp \ static_analysis.cpp \ uncaught_exceptions_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(*) From 57ecd7ba0a2f19e77ff92c5d7b6f99cf6b828005 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Feb 2017 11:54:19 +0000 Subject: [PATCH 013/342] 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 67519286156..86df683ef2a 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -35,6 +35,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 f0fc6a7f10382e905ca0fead673c5f3f016accb9 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Feb 2017 12:18:15 +0000 Subject: [PATCH 014/342] 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 ff04300c5c0..ccf64867840 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: 7, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_02/test.desc b/regression/goto-analyzer/constant_propagation_02/test.desc index 1aed1891945..a20b7029ae7 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: 8, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_03/test.desc b/regression/goto-analyzer/constant_propagation_03/test.desc index 1aed1891945..4d03e2dc47f 100644 --- a/regression/goto-analyzer/constant_propagation_03/test.desc +++ b/regression/goto-analyzer/constant_propagation_03/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --simplify out.gb +--variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_04/test.desc b/regression/goto-analyzer/constant_propagation_04/test.desc index 1aed1891945..4d03e2dc47f 100644 --- a/regression/goto-analyzer/constant_propagation_04/test.desc +++ b/regression/goto-analyzer/constant_propagation_04/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --simplify out.gb +--variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_05/test.desc b/regression/goto-analyzer/constant_propagation_05/test.desc index 2a351a220f9..d5f6be414b7 100644 --- a/regression/goto-analyzer/constant_propagation_05/test.desc +++ b/regression/goto-analyzer/constant_propagation_05/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --verify +--variable --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 11 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 fd34f106869..91ec512baf9 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\] line 11 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 71416697fd4..aa40be5ba31 100644 --- a/regression/goto-analyzer/constant_propagation_07/test.desc +++ b/regression/goto-analyzer/constant_propagation_07/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --simplify out.gb +--variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 3, assigns: 13, 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 1c0f0d10583..4a65752e619 100644 --- a/regression/goto-analyzer/constant_propagation_09/test.desc +++ b/regression/goto-analyzer/constant_propagation_09/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --verify +--variable --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 0: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_10/test.desc b/regression/goto-analyzer/constant_propagation_10/test.desc index e34ac581388..c2b7e5e5be8 100644 --- a/regression/goto-analyzer/constant_propagation_10/test.desc +++ b/regression/goto-analyzer/constant_propagation_10/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --verify +--variable --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 10 assertion a\[(\(signed( long)? long int\))?0\] == 2: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_11/test.desc b/regression/goto-analyzer/constant_propagation_11/test.desc index 8b5049d2894..20931cc56ce 100644 --- a/regression/goto-analyzer/constant_propagation_11/test.desc +++ b/regression/goto-analyzer/constant_propagation_11/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --verify +--variable --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 1: SUCCESS$ diff --git a/regression/goto-analyzer/constant_propagation_12/test.desc b/regression/goto-analyzer/constant_propagation_12/test.desc index 50879584471..6d4a4993400 100644 --- a/regression/goto-analyzer/constant_propagation_12/test.desc +++ b/regression/goto-analyzer/constant_propagation_12/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --simplify out.gb +--variable --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 7, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_13/test.desc b/regression/goto-analyzer/constant_propagation_13/test.desc index 91a78a1df7a..9c684e60b06 100644 --- a/regression/goto-analyzer/constant_propagation_13/test.desc +++ b/regression/goto-analyzer/constant_propagation_13/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --verify +--variable --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 9 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 e74316180d5..8926b873f4f 100644 --- a/regression/goto-analyzer/constant_propagation_14/test.desc +++ b/regression/goto-analyzer/constant_propagation_14/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --verify +--variable --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 11 assertion tmp_if_expr: SUCCESS$ diff --git a/regression/goto-analyzer/constant_propagation_15/test.desc b/regression/goto-analyzer/constant_propagation_15/test.desc index bf760877b4a..5a8fbdb2d97 100644 --- a/regression/goto-analyzer/constant_propagation_15/test.desc +++ b/regression/goto-analyzer/constant_propagation_15/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --verify +--variable --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 2: FAILURE \(if reachable\)$ From 2c49f9631445ee76c2921598ea79e34ff9477935 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 21 Feb 2017 10:38:11 +0000 Subject: [PATCH 015/342] 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 5134fbe5702451421c9968bdff16e5068496ddfe Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 21 Feb 2017 15:37:16 +0000 Subject: [PATCH 016/342] 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 2da41535debe7ac5211c86bc2862cc1ef70a9cea Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 21 Feb 2017 16:49:31 +0000 Subject: [PATCH 017/342] 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 86df683ef2a..9b4fed62204 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -36,7 +36,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 6cc2ff173b084372cc4059320b58f77568e205d6 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 21 Feb 2017 18:04:14 +0000 Subject: [PATCH 018/342] 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 bdbf17f26ea69dc2beedd5875c0a621b0d9b2da1 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 22 Feb 2017 10:31:19 +0000 Subject: [PATCH 019/342] 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 88043578197ffe5541fc8b70a51194105fed2d9d Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 22 Feb 2017 11:17:38 +0000 Subject: [PATCH 020/342] 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 66f0333b9a4dde0f46e6394e0a3238109ba27d62 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 22 Feb 2017 14:09:04 +0000 Subject: [PATCH 021/342] 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 9855f570e38dc4567799dbc9d5189eaa6cb05957 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 22 Feb 2017 15:54:04 +0000 Subject: [PATCH 022/342] 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 e3ab961f7fd83740d8b60179601bfadd09643440 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 22 Feb 2017 15:54:21 +0000 Subject: [PATCH 023/342] 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 47aaa55bbe184f7670075256ecd621630e21041c Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Feb 2017 09:24:37 +0000 Subject: [PATCH 024/342] 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 f46743ea8c8b857123ee3298b8ebce620e6e377f Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Feb 2017 11:27:50 +0000 Subject: [PATCH 025/342] 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 27ecc9a92a20b4b9a3385169ae3c1d06d8197721 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Feb 2017 12:26:51 +0000 Subject: [PATCH 026/342] 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 e0ddf604ea530134f2da3575359ac39ce361e2d3 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Feb 2017 14:00:28 +0000 Subject: [PATCH 027/342] 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 32f688363997934669fa8dbf93d29341317caacb Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Feb 2017 17:52:00 +0000 Subject: [PATCH 028/342] 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 487e1172a44775e5ab24a44903a45be75c1d9d84 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 24 Feb 2017 13:39:15 +0000 Subject: [PATCH 029/342] 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 6bb16bf0d5ffb7c4e32f5df13e03c66f5320b184 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 24 Feb 2017 15:06:14 +0000 Subject: [PATCH 030/342] 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 8aa09060d9408e256f30bc595a624e6d1130e520 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 24 Feb 2017 17:04:48 +0000 Subject: [PATCH 031/342] 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 685b238c2458ba1a863b2b3acc21f08b6219bc73 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 27 Feb 2017 16:48:19 +0000 Subject: [PATCH 032/342] 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 82a2199b05e125eb17487e1536de537a939b2e81 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 15:04:39 +0000 Subject: [PATCH 033/342] Add previously written design documentation to the relevant parts of the code. --- .../variable_sensitivity_domain.h | 54 +++++++++++++++++++ 1 file changed, 54 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 From a1a5bde0c44e96d39e2b5e149aee7f8c1141af61 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 15:32:09 +0000 Subject: [PATCH 034/342] 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 cacb5054ef9088133be00e96d419c1f407198609 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 15:56:34 +0000 Subject: [PATCH 035/342] 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 7ae5cdde4ee3a1305a4ad1f49b62f094768c0401 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 15:59:59 +0000 Subject: [PATCH 036/342] 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 cb55d48b6075bd2afa8dc2fdf73da6809d4243d3 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 27 Feb 2017 16:54:13 +0000 Subject: [PATCH 037/342] 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 9b4fed62204..449c0327d0a 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -38,6 +38,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 94d530ad31a78ac1f07701c5aa7870964603a8b0 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 27 Feb 2017 17:02:37 +0000 Subject: [PATCH 038/342] 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 d51b21c7958f8b77b9a11976011f65b0bdbcfa55 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 10:57:45 +0000 Subject: [PATCH 039/342] 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 9a039252f68cbf817a896ea28c278fcaaf6139a2 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 13:42:04 +0000 Subject: [PATCH 040/342] 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 18669de5e84653e1071abf1ec880036fe7a4e234 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 14:18:35 +0000 Subject: [PATCH 041/342] 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 27651476a044d164bd797e653cb1a17bf19ac322 Mon Sep 17 00:00:00 2001 From: Owen Jones Date: Tue, 28 Feb 2017 15:00:32 +0000 Subject: [PATCH 042/342] 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 ++++++ 13 files changed, 255 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 449c0327d0a..6a445a6f01e 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -42,6 +42,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 From d695106411414d9431e1b86ba65a7342301eaecf Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 18:43:11 +0000 Subject: [PATCH 043/342] 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 4b3316e76934ce78770e1bb04aa659e5e0b063ef Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 18:45:11 +0000 Subject: [PATCH 044/342] 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 6107a1c68ae0222263f142e3f95d58493c545067 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 16:24:35 +0000 Subject: [PATCH 045/342] 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 b6576b6475db6bc2c9631c355ededb6a0950f186 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 18:45:51 +0000 Subject: [PATCH 046/342] 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 5469d3a1dd489574e37a925d52eeb09c273975ca Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 19:18:59 +0000 Subject: [PATCH 047/342] 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 27efb249b66..b950758247c 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 4f7f3d7a299..41778f5bd81 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 b8f474c3d55..8802cba51b5 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 887f9ec7b8f..4209a80c3c8 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 1591fb003ca..d101f2b0b27 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 cdf43ec8535..be1bddba8b4 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 131d372007f..c30c3de7b95 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 8ad08e49dc7..e41c27b0500 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 7abf2edbdf4ddf0adea9ff153f48d5a48ffe9c81 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Feb 2017 19:30:29 +0000 Subject: [PATCH 048/342] 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 fdb59ebd7734d158df5bf4a48d0b5c40a30511d9 Mon Sep 17 00:00:00 2001 From: Owen Jones Date: Thu, 2 Mar 2017 15:56:32 +0000 Subject: [PATCH 049/342] 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 baf9b6ea658d1129e119c498c9b716ff7078cbec Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 5 Dec 2017 18:20:26 +0000 Subject: [PATCH 050/342] Tweak the signature of the object factory. --- .../variable_sensitivity_object_factory.cpp | 2 +- .../variable-sensitivity/variable_sensitivity_object_factory.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index fb034763ef1..7fdca1fdcba 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -142,7 +142,7 @@ Function: variable_sensitivity_object_factoryt::set_options \*******************************************************************/ -void variable_sensitivity_object_factoryt::set_options(optionst &options) +void variable_sensitivity_object_factoryt::set_options(const optionst &options) { has_variables_flag=options.get_bool_option("variable"); has_structs_flag=options.get_bool_option("structs"); diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index 21346d01413..25595b53bf5 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -26,7 +26,7 @@ class variable_sensitivity_object_factoryt abstract_object_pointert get_abstract_object( const typet type, bool top, bool bottom, const exprt &e, const namespacet &ns); - void set_options(optionst &options); + void set_options(const optionst &options); private: variable_sensitivity_object_factoryt():initialized(false) From 607017374d9d3256651b259bbe85f498fd8ed9c0 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 20:21:56 +0000 Subject: [PATCH 051/342] 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 8f6be50aeb4c27dc79f323b8fd19dca87168f820 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 20:37:39 +0000 Subject: [PATCH 052/342] 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 67f91e75cad10f140387091d95df0337803add57 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 28 Feb 2017 20:57:37 +0000 Subject: [PATCH 053/342] 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 253172b88a82600912412cb49e2e45d8d81b3aeb Mon Sep 17 00:00:00 2001 From: martin Date: Thu, 2 Mar 2017 20:48:45 +0000 Subject: [PATCH 054/342] 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 f0ad68ec65dacb79718ffe01e5608144b3df73d8 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 6 Mar 2017 19:41:13 +0000 Subject: [PATCH 055/342] 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 f8c469c62a711fb3262c52c1540705008ea13fcd Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 6 Mar 2017 20:38:46 +0000 Subject: [PATCH 056/342] 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 06d7913ecd737d146dd70c1ad1d6292bd569db01 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 6 Mar 2017 20:50:47 +0000 Subject: [PATCH 057/342] 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 0e76cafe16c33f8d7a6121b2bff5cd613a744ace Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Mon, 27 Feb 2017 18:39:47 +0000 Subject: [PATCH 058/342] 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 6a445a6f01e..2ae9c52f9f7 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -43,6 +43,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 7fdca1fdcba..33880bbee3c 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 25595b53bf5..33e79386566 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 0f377f542f854f506c909517698ca20ef22654bc Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 6 Mar 2017 18:21:46 +0000 Subject: [PATCH 059/342] 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 2e3e29d6d4dce3ace22cb8a844ad5209d8a9e9c5 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 6 Mar 2017 19:25:15 +0000 Subject: [PATCH 060/342] 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 e92a19ef927..b21c1a29834 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 33880bbee3c..87478ed9f43 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 adc1330c341e0b91aa4531961d951f33e0943d6b Mon Sep 17 00:00:00 2001 From: Owen Jones Date: Wed, 8 Mar 2017 17:11:00 +0000 Subject: [PATCH 061/342] 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 cb963b7e3879feb47b5fd50966e067fd97494e82 Mon Sep 17 00:00:00 2001 From: martin Date: Thu, 9 Mar 2017 20:26:27 +0000 Subject: [PATCH 062/342] 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 fd1e0870e83c0296b5ee25ac43a9a486bae8af54 Mon Sep 17 00:00:00 2001 From: martin Date: Thu, 9 Mar 2017 20:44:57 +0000 Subject: [PATCH 063/342] 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 4615be87c504afd32df5b4f4e30170ff2f8940f0 Mon Sep 17 00:00:00 2001 From: Owen Jones Date: Thu, 9 Mar 2017 11:50:54 +0000 Subject: [PATCH 064/342] 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 f6df2f6ed012a896cd39ebbe5834e7fd489e59ab Mon Sep 17 00:00:00 2001 From: Owen Jones Date: Thu, 9 Mar 2017 15:15:47 +0000 Subject: [PATCH 065/342] 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 10e7d1c35ee6fb786f69528a6118c958d78df785 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Mar 2017 17:18:57 +0000 Subject: [PATCH 066/342] 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 7467b22d21b0f2ea0086161719fb1438ad33e81f Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Mar 2017 17:18:37 +0000 Subject: [PATCH 067/342] 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 f759f5636d9215afee9a8bea401977977a27a67b Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Mar 2017 17:19:20 +0000 Subject: [PATCH 068/342] 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 caad73119347f54128691b58dd32cf61c382d838 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Mar 2017 18:04:19 +0000 Subject: [PATCH 069/342] 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 33e79386566..359c91ef114 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 c38dd8e8047464f2009d871585364c8f20df8194 Mon Sep 17 00:00:00 2001 From: Owen Jones Date: Tue, 7 Mar 2017 16:59:21 +0000 Subject: [PATCH 070/342] 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 6897273973f69abc212925d5d976a9f993519553 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 10 Mar 2017 17:33:34 +0000 Subject: [PATCH 071/342] 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 2ae9c52f9f7..eba507c95e7 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -43,7 +43,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 87478ed9f43..c5de3bc1921 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 359c91ef114..f36e1a0b73d 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 06c07aa88db24e1a942c7003d33a8b1611273b45 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 15 Mar 2017 11:44:13 +0000 Subject: [PATCH 072/342] 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 c5de3bc1921..47c6403e8b5 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 f36e1a0b73d..d138e1ad17d 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(const 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 72cc42bfb059c0e9c03474462ceeacc9faa80574 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 16 Mar 2017 10:48:02 +0000 Subject: [PATCH 073/342] 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 194d7fde492fa47522b3013e1da58e4149bb93d8 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 16 Mar 2017 16:29:29 +0000 Subject: [PATCH 074/342] 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 697e1f509e90e7a676f677b59c2d85642d9170d3 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Mar 2017 11:26:34 +0000 Subject: [PATCH 075/342] 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 095e7e0b0e42b8c94e5f925bd8a97e01895cdf81 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 17 Mar 2017 11:26:24 +0000 Subject: [PATCH 076/342] 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 51c37288d51aa23845ce51f76ad473f580459cbc Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Mar 2017 09:42:20 +0000 Subject: [PATCH 077/342] 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 66780194ab00bb4bb9a6c3f27b2418f00894203c Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Mar 2017 09:43:59 +0000 Subject: [PATCH 078/342] 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 22f1c59cc5f79f73fb32901e50714c3eacbf0cef Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Mar 2017 09:47:11 +0000 Subject: [PATCH 079/342] 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 05bdde68a64..642e8d5e379 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 efd52978d50..3f0f4c12a1c 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 1cfdb337e9a..f0d94c87d95 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 25cfc93eee0..5024f940d51 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 9ac2425b7bf..f5113279c5b 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 599a644d13d..3147873ee81 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 72da73df05e..6eba23426b6 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 243aa1735a8..a9814c7b575 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 6f339498c07..f2d0cba5aeb 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 d4fb9dbbbd4..efc37a4e68f 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 9d0b92caee5..e7d0978e573 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 8d313d09da8b4817bb94aab81ecc07be63cd21e3 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Mar 2017 10:10:10 +0000 Subject: [PATCH 080/342] 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 e1c50e98ed7..9199e17f2f1 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 732c3a3bfa6..683df8e18d6 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 bb6c1ee2f7a..c5ac1be1172 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 99372ff72af..89a89ddfc2e 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 da6eb8848c7..f7c6f5ce685 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 57f31ec109a..06e46404bb6 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 c75dec8b757..6ed3b308c55 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 3d06e1f7e0d..327c9291e60 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 8e076119b4e..85dd34130c7 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 b1716e297112dcea5a04d94702b407ad9cc02fc0 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 23 Mar 2017 10:18:07 +0000 Subject: [PATCH 081/342] 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 fa8f5e6ced1387fff9834433df4eeb4c02909ffd Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 24 Mar 2017 10:06:14 +0000 Subject: [PATCH 082/342] 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 e2c0950c1e54ca6b4daa231421dc38319cf59e33 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 27 Mar 2017 14:54:12 +0100 Subject: [PATCH 083/342] 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 3005fea59258df313efe3dd6b59755a864ab6d50 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Mar 2017 13:27:06 +0100 Subject: [PATCH 084/342] 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 c6e485e8b026bb15855ac159106975c2f9a02a3a Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Mar 2017 14:25:06 +0100 Subject: [PATCH 085/342] 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 190b9c7e26f599aefe1265f3968767d3a811e116 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Mar 2017 14:30:33 +0100 Subject: [PATCH 086/342] 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 c203fa1ab37c8615249fe182e4ed2762c8f9b773 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Mar 2017 17:12:14 +0100 Subject: [PATCH 087/342] 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 | 2 +- .../constant_propagation_02/test.desc | 2 +- .../constant_propagation_07/test.desc | 2 +- .../constant_propagation_08/test.desc | 4 ++-- .../constant_propagation_09/test.desc | 4 ++-- .../constant_propagation_10/test.desc | 4 ++-- .../constant_propagation_11/test.desc | 2 +- .../constant_propagation_12/test.desc | 2 +- .../constant_propagation_13/test.desc | 2 +- .../constant_propagation_14/test.desc | 6 +++--- .../constant_propagation_15/test.desc | 4 ++-- .../variable_sensitivity_domain.cpp | 21 +++++++++---------- 13 files changed, 30 insertions(+), 30 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 ccf64867840..576370a0c05 100644 --- a/regression/goto-analyzer/constant_propagation_01/test.desc +++ b/regression/goto-analyzer/constant_propagation_01/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE main.c --variable --simplify out.gb ^EXIT=0$ diff --git a/regression/goto-analyzer/constant_propagation_02/test.desc b/regression/goto-analyzer/constant_propagation_02/test.desc index a20b7029ae7..4d03e2dc47f 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_07/test.desc b/regression/goto-analyzer/constant_propagation_07/test.desc index aa40be5ba31..e014e66bd22 100644 --- a/regression/goto-analyzer/constant_propagation_07/test.desc +++ b/regression/goto-analyzer/constant_propagation_07/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --variable --simplify out.gb ^EXIT=0$ 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 4a65752e619..efd54ca17aa 100644 --- a/regression/goto-analyzer/constant_propagation_09/test.desc +++ b/regression/goto-analyzer/constant_propagation_09/test.desc @@ -1,6 +1,6 @@ -CORE +KNOWNBUG main.c ---variable --verify +--variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 0: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_10/test.desc b/regression/goto-analyzer/constant_propagation_10/test.desc index c2b7e5e5be8..37206fe4887 100644 --- a/regression/goto-analyzer/constant_propagation_10/test.desc +++ b/regression/goto-analyzer/constant_propagation_10/test.desc @@ -1,8 +1,8 @@ CORE main.c ---variable --verify +--variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 10 assertion a\[(\(signed( long)? long int\))?0\] == 2: FAILURE \(if reachable\)$ +^\[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 20931cc56ce..8c5f8a279be 100644 --- a/regression/goto-analyzer/constant_propagation_11/test.desc +++ b/regression/goto-analyzer/constant_propagation_11/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --verify +--variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 1: SUCCESS$ diff --git a/regression/goto-analyzer/constant_propagation_12/test.desc b/regression/goto-analyzer/constant_propagation_12/test.desc index 6d4a4993400..3ac7d06ccad 100644 --- a/regression/goto-analyzer/constant_propagation_12/test.desc +++ b/regression/goto-analyzer/constant_propagation_12/test.desc @@ -1,4 +1,4 @@ -CORE +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 9c684e60b06..8837d5ca5a0 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\] line 9 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 8926b873f4f..402f6bf6700 100644 --- a/regression/goto-analyzer/constant_propagation_14/test.desc +++ b/regression/goto-analyzer/constant_propagation_14/test.desc @@ -1,9 +1,9 @@ CORE main.c ---variable --verify +--variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 11 assertion tmp_if_expr: SUCCESS$ -^\[main.assertion.2\] line 12 assertion tmp_if_expr\$0: FAILURE \(if reachable\)$ +^\[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 5a8fbdb2d97..99fe073380a 100644 --- a/regression/goto-analyzer/constant_propagation_15/test.desc +++ b/regression/goto-analyzer/constant_propagation_15/test.desc @@ -1,8 +1,8 @@ CORE main.c ---variable --verify +--variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 2: FAILURE \(if reachable\)$ +^\[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 77a2e58d5a9f53abd1ac292ab39ffeefe288364f Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 28 Mar 2017 18:12:57 +0100 Subject: [PATCH 088/342] 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 e693823e79f4701f8ed3827db2786526009dc4ad Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 29 Mar 2017 17:25:38 +0100 Subject: [PATCH 089/342] 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 6b6f2338907ff0ac9c20a2ff4a1dfb9e670e9d74 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 19 Apr 2017 17:01:45 +0100 Subject: [PATCH 090/342] 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 b21c1a29834..1e6938499be 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 043389d01f44c5301a5f6aed56f8e69cc1a93a0b Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 5 Apr 2017 11:14:09 +0100 Subject: [PATCH 091/342] 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 f7c6f5ce685..4ec326af073 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 06e46404bb6..b8c72f167f2 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 d101f2b0b27..aeae8e8ffb3 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 3c36947f9b18990f3cd80625d0a73dd39f652016 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 7 Apr 2017 11:32:40 +0100 Subject: [PATCH 092/342] 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 4ec326af073..ba893d343a8 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 b8c72f167f2..17746aba81b 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 aeae8e8ffb3..396838d861a 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 9d6ed2d562e0a1c81814b4ec0b16e3a17aa46a0d Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 11 Apr 2017 14:56:54 +0100 Subject: [PATCH 093/342] 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 683df8e18d6..12ef67f3f4b 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 c5ac1be1172..3ecb3c45e39 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 327c9291e60..1a7b1120e8a 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 c02621e83929f576082d7a9b0bbe54af0d6c1e8e Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 21 Apr 2017 14:22:44 +0100 Subject: [PATCH 094/342] 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 22c5a8ded10d42156242b17cd9eee430baaacb05 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 21 Apr 2017 14:27:29 +0100 Subject: [PATCH 095/342] 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 4472561b73ac41fbe0724c97935304d2826af9dc Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 24 Apr 2017 15:17:31 +0100 Subject: [PATCH 096/342] 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 13a4508455254a58900bfa4dac7fc66892d22351 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 24 Apr 2017 15:19:32 +0100 Subject: [PATCH 097/342] 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 4e1846982df64593e0af93e0482e05cd1f30893c Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 25 Apr 2017 10:21:26 +0100 Subject: [PATCH 098/342] 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 8a04c6ec50452f3dc40c4b8dbfc4fafb0ef8491d Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 25 Apr 2017 11:28:00 +0100 Subject: [PATCH 099/342] 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 579a84bce3325f56a033838faeae08c378543b55 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 25 Apr 2017 14:29:49 +0100 Subject: [PATCH 100/342] 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 75fb0e52368..e0d55ffad5a 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -14,6 +14,7 @@ SRC += analyses/ai/ai.cpp \ analyses/does_remove_const/does_expr_lose_const.cpp \ analyses/does_remove_const/does_type_preserve_const_correctness.cpp \ analyses/does_remove_const/is_type_at_least_as_const_as.cpp \ + analyses/variable-sensitivity/abstract_object/merge.cpp \ ansi-c/max_malloc_size.cpp \ ansi-c/type2name.cpp \ big-int/big-int.cpp \ 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 13dceae4f238a9ba61dde503d21f1b7ee4db3a28 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 25 Apr 2017 17:36:58 +0100 Subject: [PATCH 101/342] 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 a25a039144e4877f0cdae9398fed3d55bdcf8207 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 25 Apr 2017 17:37:45 +0100 Subject: [PATCH 102/342] 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 e0d55ffad5a..b210c2fd6cf 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -15,6 +15,7 @@ SRC += analyses/ai/ai.cpp \ analyses/does_remove_const/does_type_preserve_const_correctness.cpp \ analyses/does_remove_const/is_type_at_least_as_const_as.cpp \ analyses/variable-sensitivity/abstract_object/merge.cpp \ + analyses/variable-sensitivity/constant_abstract_value/merge.cpp \ ansi-c/max_malloc_size.cpp \ ansi-c/type2name.cpp \ big-int/big-int.cpp \ 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 db1d258f16af453ff638bafa34f5c1644c8e0a20 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 27 Apr 2017 18:02:09 +0100 Subject: [PATCH 103/342] 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 47c6403e8b5..7e8dadd2a15 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 b210c2fd6cf..d67c498710e 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -16,6 +16,7 @@ SRC += analyses/ai/ai.cpp \ analyses/does_remove_const/is_type_at_least_as_const_as.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 \ ansi-c/max_malloc_size.cpp \ ansi-c/type2name.cpp \ big-int/big-int.cpp \ 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 9303f9b80a497a1a04fc5e6b50da6b8224113141 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 28 Apr 2017 11:47:52 +0100 Subject: [PATCH 104/342] 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 d67c498710e..758520e9018 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -17,6 +17,7 @@ SRC += analyses/ai/ai.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 \ ansi-c/max_malloc_size.cpp \ ansi-c/type2name.cpp \ big-int/big-int.cpp \ 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 1bc8f48edf544a3788b1af30e224b1e0f98c8b52 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 28 Apr 2017 11:49:57 +0100 Subject: [PATCH 105/342] 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 4f4443a380644c69fc7758b44da8564a88de1df8 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 28 Apr 2017 15:56:06 +0100 Subject: [PATCH 106/342] 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 478d5df159cc839a2f3417191caca81a841ee5ad Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 2 May 2017 17:49:17 +0100 Subject: [PATCH 107/342] 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_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 +-- 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 +-- 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 +- 94 files changed, 1183 insertions(+), 1183 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_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 d5f6be414b7..f608823f827 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\] line 11 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 91ec512baf9..ac2aec727c4 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\] line 11 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 8837d5ca5a0..8ced11a1357 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 402f6bf6700..6a3a4b25fd6 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 99fe073380a..4aafae8319e 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 31c2928c262..94b0034f356 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\] line 12 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 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 && j2) { - 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 9199e17f2f1..d6beba0c05f 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 12ef67f3f4b..664404a4ab7 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 3ecb3c45e39..de16c370dd5 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 89a89ddfc2e..79137cd1c26 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 b950758247c..3e0e11855ad 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 41778f5bd81..72c3b69b398 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 1e6938499be..4a7b276b621 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 ba893d343a8..61fddaeeef5 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 8802cba51b5..88f85ae3a7a 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 234895fc2dd..de0638dc86b 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 17746aba81b..93fafede3ed 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 642e8d5e379..4c425b0ac6e 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 4209a80c3c8..18f34a8836d 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 3f0f4c12a1c..4634e6ec09b 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 f0d94c87d95..cea1535c673 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 5024f940d51..322edb6dfc3 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 f5113279c5b..52b5a18d808 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 3147873ee81..fb7559001b3 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 6eba23426b6..35f225a3983 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 6ed3b308c55..d7de65f884a 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 1a7b1120e8a..6be850ffdb0 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 85dd34130c7..8f4ab1fe304 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 396838d861a..3bbdd3aae25 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 be1bddba8b4..d610089530a 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 c30c3de7b95..67c09b58e1f 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 e41c27b0500..9f138fce8ad 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 a9814c7b575..ef99fb84bcc 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 f2d0cba5aeb..9454d040cf6 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 efc37a4e68f..42c36b7a063 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 e7d0978e573..7193029cb7b 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 6955e2db14d37723c2ec7e6708dcdd97d26c9b19 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 5 May 2017 15:48:48 +0100 Subject: [PATCH 108/342] 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 331967f42148366f8ca2dd1bbd61ed811102b015 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 5 May 2017 16:34:48 +0100 Subject: [PATCH 109/342] 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 1a775e95a9ce94a81f3175019f2f1090ed5fef29 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 5 May 2017 18:29:11 +0100 Subject: [PATCH 110/342] 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 3c2c184e5be380bc7b702f642db994c92b058be8 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 5 May 2017 18:29:33 +0100 Subject: [PATCH 111/342] 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 19fa326a1e76ce9930d390dad9111c8787797d63 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 5 May 2017 18:29:49 +0100 Subject: [PATCH 112/342] 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 662f65548c2aab0b05a5b6208a0fc8f1126a39de Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 5 May 2017 18:30:19 +0100 Subject: [PATCH 113/342] 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 2fd13c4c557a316e14579adfc06b62c10b2019d5 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 9 May 2017 12:29:46 +0100 Subject: [PATCH 114/342] 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 c5ec42ffa58ac32d993fe64aa645e888afad23ba Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 11 May 2017 11:36:14 +0100 Subject: [PATCH 115/342] 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 da4250bb5f07b01193452e5993232d7e7e2b8302 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 16 May 2017 17:14:34 +0100 Subject: [PATCH 116/342] 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 ccf535157687c70b04f6c711e2c00f086119abe6 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 15 Jun 2017 17:52:41 +0100 Subject: [PATCH 117/342] 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; }; From c4f1d521cca9d9887ec386607ca969a98a86552a Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Mon, 10 Apr 2017 17:58:00 +0100 Subject: [PATCH 118/342] Implemented the sensitivity domain for the union abstract object. Adjusted to fit with the modifications on the variable sensitivity domain --- src/analyses/Makefile | 1 + .../abstract_enviroment.cpp | 54 +++++-- .../union_abstract_object.cpp | 144 ++++++++++++++++++ .../union_abstract_object.h | 47 ++++++ .../variable_sensitivity_object_factory.cpp | 5 +- .../variable_sensitivity_object_factory.h | 5 +- 6 files changed, 243 insertions(+), 13 deletions(-) create mode 100644 src/analyses/variable-sensitivity/union_abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/union_abstract_object.h diff --git a/src/analyses/Makefile b/src/analyses/Makefile index eba507c95e7..f1975f646a0 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -45,6 +45,7 @@ SRC = ai.cpp \ variable-sensitivity/variable_sensitivity_object_factory.cpp \ variable-sensitivity/full_struct_abstract_object.cpp \ variable-sensitivity/constant_array_abstract_object.cpp \ + variable-sensitivity/union_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 b16e0602c69..c7974d588a8 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -67,11 +67,24 @@ abstract_object_pointert abstract_environmentt::eval( { member_exprt member_expr(to_member_expr(simplified_expr)); - sharing_ptrt struct_abstract_object= - std::dynamic_pointer_cast( - eval(member_expr.compound(), ns)); + const exprt &parent = member_expr.compound(); + bool is_union = ns.follow(parent.type()).id() == ID_union; - return struct_abstract_object->read_component(*this, member_expr, ns); + if(is_union) + { + sharing_ptrt union_abstract_object= + std::dynamic_pointer_cast( + eval(parent, ns)); + + return union_abstract_object->read_component(*this, member_expr, ns); + } + else + { // is struct + sharing_ptrt struct_abstract_object= + std::dynamic_pointer_cast( + eval(member_expr.compound(), ns)); + return struct_abstract_object->read_component(*this, member_expr, ns); + } } else if(simplified_id==ID_address_of) { @@ -308,15 +321,34 @@ abstract_object_pointert abstract_environmentt::write( } else if(stack_head_id==ID_member) { - sharing_ptrt struct_abstract_object= - std::dynamic_pointer_cast(lhs); - 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); + const member_exprt &member_expr = to_member_expr(next_expr); + const exprt &parent = member_expr.compound(); + bool is_union = ns.follow(parent.type()).id() == ID_union; + + if(is_union) + { + sharing_ptrt union_abstract_object= + std::dynamic_pointer_cast(lhs); + + sharing_ptrt modified_union= + union_abstract_object->write_component( + *this, ns, remaining_stack, member_expr, rhs, merge_write); - return modified_struct; + return modified_union; + } + else + { + sharing_ptrt struct_abstract_object= + std::dynamic_pointer_cast(lhs); + + 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) { diff --git a/src/analyses/variable-sensitivity/union_abstract_object.cpp b/src/analyses/variable-sensitivity/union_abstract_object.cpp new file mode 100644 index 00000000000..aec3eb457d9 --- /dev/null +++ b/src/analyses/variable-sensitivity/union_abstract_object.cpp @@ -0,0 +1,144 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Fotis Koutoulakis, fotis.koutoulakis@diffblue.com + +\*******************************************************************/ + +#include +#include +#include + +#include "union_abstract_object.h" + + +/*******************************************************************\ + +Function: union_abstract_objectt::union_abstract_objectt + + Inputs: + type - the type the abstract_object is representing + + Outputs: + + Purpose: + +\*******************************************************************/ + +union_abstract_objectt::union_abstract_objectt(const typet &type): + abstract_objectt(type) +{ + assert(type.id()==ID_union); +} + +/*******************************************************************\ + +Function: union_abstract_objectt::union_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 + +\*******************************************************************/ + +union_abstract_objectt::union_abstract_objectt( + const typet &type, bool top, bool bottom): + abstract_objectt(type, top, bottom) +{ + assert(type.id()==ID_union); +} + +/*******************************************************************\ + +Function: union_abstract_objectt::union_abstract_objectt + + Inputs: + expr - the expression to use as the starting pointer for an abstract object + environment - the environment the abstract object is going to be evaluated in. + + Outputs: + + Purpose: + +\*******************************************************************/ + +union_abstract_objectt::union_abstract_objectt( + const exprt &expr, const abstract_environmentt &environment, + const namespacet &ns): + abstract_objectt(expr, environment, ns) +{ + assert(ns.follow(expr.type()).id()==ID_union); +} + +/*******************************************************************\ + +Function: union_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 union. + + Purpose: A helper function to evaluate the abstract object contained + within a union. More precise abstractions may override this + to return more precise results. + +\*******************************************************************/ + +abstract_object_pointert union_abstract_objectt::read_component( + const abstract_environmentt &environment, + const member_exprt &member_expr, + const namespacet &ns) const +{ + return environment.abstract_object_factory( + member_expr.type(), ns, !is_bottom(), is_bottom()); +} + +/*******************************************************************\ + +Function: union_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 union_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 union. + + Purpose: A helper function to evaluate writing to a component of a union. + More precise abstractions may override this to + update what they are storing for a specific component. + +\*******************************************************************/ + +sharing_ptrt union_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 +{ + if(is_top() || is_bottom()) + { + return std::dynamic_pointer_cast(clone()); + } + else + { + return sharing_ptrt( + new union_abstract_objectt(type(), true, false)); + } +} diff --git a/src/analyses/variable-sensitivity/union_abstract_object.h b/src/analyses/variable-sensitivity/union_abstract_object.h new file mode 100644 index 00000000000..e9c9a76807a --- /dev/null +++ b/src/analyses/variable-sensitivity/union_abstract_object.h @@ -0,0 +1,47 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Fotis Koutoulakis, fotis.koutoulakis@diffblue.com + +\*******************************************************************/ + +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_UNION_ABSTRACT_OBJECT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_UNION_ABSTRACT_OBJECT_H + +#include +#include + +class abstract_environmentt; +class member_exprt; + +class union_abstract_objectt:public abstract_objectt +{ +public: + explicit union_abstract_objectt(const typet &type); + union_abstract_objectt(const typet &type, bool top, bool bottom); + explicit union_abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); + + // union interface + virtual abstract_object_pointert read_component( + const abstract_environmentt &environment, + const member_exprt &member_expr, + const namespacet &ns) const; + + 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) const; + +protected: + CLONE +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_UNION_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 7e8dadd2a15..39e6eca3c48 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -51,7 +51,7 @@ variable_sensitivity_object_factoryt::ABSTRACT_OBJECT_TYPET } else if(type.id()==ID_union) { - // TODO: deal with unions + abstract_object_type=UNION_INSENSITIVE; } return abstract_object_type; @@ -119,6 +119,9 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: case STRUCT_INSENSITIVE: return initialize_abstract_object( followed_type, top, bottom, e, environment, ns); + case UNION_INSENSITIVE: + return initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); case TWO_VALUE: return initialize_abstract_object( 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 d138e1ad17d..b8f4e2381f4 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 #include #include @@ -48,7 +49,9 @@ class variable_sensitivity_object_factoryt POINTER_SENSITIVE, POINTER_INSENSITIVE, STRUCT_SENSITIVE, - STRUCT_INSENSITIVE + STRUCT_INSENSITIVE, + // TODO: plug in UNION_SENSITIVE HERE + UNION_INSENSITIVE }; ABSTRACT_OBJECT_TYPET get_abstract_object_type(const typet type); template From 5c839460946595bf80eb3e68abf4067336a16b85 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 24 Mar 2017 14:14:30 +0000 Subject: [PATCH 119/342] Added implementation for transition into/out of function calls The transform function now handles function calls (copy the values of the parameters into appropriately named abstract objects) and function return (erase the values of the parameters from the domain. --- .../variable_sensitivity_domain.cpp | 82 ++++++++++++++++++- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 6832d635055..288fb78d865 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -14,6 +14,7 @@ Date: April 2016 #include #include "variable_sensitivity_domain.h" +#include #ifdef DEBUG #include @@ -106,12 +107,89 @@ void variable_sensitivity_domaint::transform( break; case FUNCTION_CALL: - // FIXME : Ignore as not yet interprocedural + { + 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) + { + // called function identifier + const symbol_exprt &symbol_expr=to_symbol_expr(function); + const irep_idt function_id=symbol_expr.get_identifier(); + + + if(to==next) + { + if(function_id==CPROVER_PREFIX "set_must" || + function_id==CPROVER_PREFIX "get_must" || + function_id==CPROVER_PREFIX "set_may" || + function_id==CPROVER_PREFIX "get_may" || + function_id==CPROVER_PREFIX "cleanup" || + function_id==CPROVER_PREFIX "clear_may" || + function_id==CPROVER_PREFIX "clear_must") + { + // no effect on constants + } + else + { + assert(false); + } + } + else + { + // we have an actual call + + // parameters of called function + const symbolt &symbol=ns.lookup(function_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(); + + code_typet::parameterst::const_iterator p_it=parameters.begin(); + for(const auto &arg : arguments) + { + if(p_it==parameters.end()) + break; + + const symbol_exprt parameter_expr(p_it->get_identifier(), arg.type()); + abstract_object_pointert param_val=abstract_state.eval(arg, ns); + abstract_state.assign(parameter_expr, param_val, ns); + + ++p_it; + } + } + } + else + { + // unresolved call + assert(false); + } break; + } case END_FUNCTION: - // FIXME : Ignore as not yet interprocedural + { + // erase parameters + + const irep_idt id=from->function; + const symbolt &symbol=ns.lookup(id); + + const code_typet &type=to_code_type(symbol.type); + + for(const auto ¶m : type.parameters()) + { + abstract_state.assign( + symbol_exprt(param.get_identifier(), param.type()), + abstract_state.abstract_object_factory(param.type(), ns, true, false), + ns); + } break; + } /***************************************************************/ From e71a2e7199c3394e4d3596a3ce5b85216112fcb9 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 24 Mar 2017 14:16:00 +0000 Subject: [PATCH 120/342] Adding tests for function calls Some of the code is commented out to disable unsupported features from the tests Disabling parts of the test dependent on pointer arithmetic --- .../sensitivity-function-call-array/main.c | 32 +++++++++++++++++++ .../sensitivity-function-call-array/test.desc | 12 +++++++ .../sensitivity-function-call-pointer/main.c | 25 +++++++++++++++ .../test.desc | 12 +++++++ .../main.c | 14 ++++++++ .../test.desc | 9 ++++++ 6 files changed, 104 insertions(+) create mode 100644 regression/goto-analyzer/sensitivity-function-call-array/main.c create mode 100644 regression/goto-analyzer/sensitivity-function-call-array/test.desc create mode 100644 regression/goto-analyzer/sensitivity-function-call-pointer/main.c create mode 100644 regression/goto-analyzer/sensitivity-function-call-pointer/test.desc create mode 100644 regression/goto-analyzer/sensitivity-function-call-primitive/main.c create mode 100644 regression/goto-analyzer/sensitivity-function-call-primitive/test.desc diff --git a/regression/goto-analyzer/sensitivity-function-call-array/main.c b/regression/goto-analyzer/sensitivity-function-call-array/main.c new file mode 100644 index 00000000000..4137d35003a --- /dev/null +++ b/regression/goto-analyzer/sensitivity-function-call-array/main.c @@ -0,0 +1,32 @@ +#include + +int *bar(int *arr_unmodified, int *arr_modified); + +int main(int argc, char *argv[]) +{ + int arr_x[] = {1, 2, 3, 4}; + int arr_y[] = {1, 2, 3, 4}; + int *p2arr = arr_x; + + p2arr = bar(arr_x, arr_y); + assert(*arr_y==2); + // assert(arr_y[1]==3); + + assert(p2arr==arr_y); + assert(*p2arr==2); + // assert(p2arr[1]==3); +} + +int *bar(int *arr_unmodified, int *arr_modified) +{ + assert(*arr_unmodified==1); + // assert(arr_unmodified[1]==2); + + (*arr_modified) += 1; + // arr_modified[1] = 3; + + assert(*arr_modified==2); + // assert(arr_modified[1]==3); + + return arr_modified; +} diff --git a/regression/goto-analyzer/sensitivity-function-call-array/test.desc b/regression/goto-analyzer/sensitivity-function-call-array/test.desc new file mode 100644 index 00000000000..14a8c38bb3a --- /dev/null +++ b/regression/goto-analyzer/sensitivity-function-call-array/test.desc @@ -0,0 +1,12 @@ +CORE +main.c +--variable --pointers --arrays --structs --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main\.assertion\.1\] .* assertion \*arr_y==2: Success$ +^\[main\.assertion\.2\] .* assertion p2arr==arr_y: Success$ +^\[main\.assertion\.3\] .* assertion \*p2arr==2: Success$ +^\[bar\.assertion\.1\] .* assertion \*arr_unmodified==1: Success$ +^\[bar\.assertion\.2\] .* assertion \*arr_modified==2: Success$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-function-call-pointer/main.c b/regression/goto-analyzer/sensitivity-function-call-pointer/main.c new file mode 100644 index 00000000000..246e40b4100 --- /dev/null +++ b/regression/goto-analyzer/sensitivity-function-call-pointer/main.c @@ -0,0 +1,25 @@ +#include + +int *bar(int *unmodified, int *modifed); + +int main(int argc, char *argv[]) +{ + int x=3; + int y=4; + int *p2x=&x; + p2x = bar(&x, &y); + assert(y==5); + assert(p2x==&y); + assert(*p2x==5); +} + +int *bar(int *unmodified, int *modifed) +{ + assert(*unmodified==3); + + (*modifed) += 1; + + assert(*modifed==5); + + return modifed; +} diff --git a/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc b/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc new file mode 100644 index 00000000000..7789cbb03da --- /dev/null +++ b/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc @@ -0,0 +1,12 @@ +CORE +main.c +--variable --pointers --arrays --structs --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main\.assertion\.1\] .* assertion y==5: Success$ +^\[main\.assertion\.2\] .* assertion p2x==&y: Success$ +^\[main\.assertion\.3\] .* assertion \*p2x==5: Success$ +^\[bar\.assertion\.1\] .* assertion \*unmodified==3: Success$ +^\[bar\.assertion\.2\] .* assertion \*modifed==5: Success$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-function-call-primitive/main.c b/regression/goto-analyzer/sensitivity-function-call-primitive/main.c new file mode 100644 index 00000000000..c9afbfc927d --- /dev/null +++ b/regression/goto-analyzer/sensitivity-function-call-primitive/main.c @@ -0,0 +1,14 @@ +#include + +int bar(int other) +{ + assert(other==4); + return other + 1; +} + +int main(int argc, char *argv[]) +{ + int x=3; + int y=bar(x+1); + assert(y==5); +} diff --git a/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc b/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc new file mode 100644 index 00000000000..18e4cd5fc0e --- /dev/null +++ b/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc @@ -0,0 +1,9 @@ +CORE +main.c +--variable --pointers --arrays --structs --verify +^EXIT=0$ +^SIGNAL=0$ +^\[bar\.assertion\.1\] .* assertion other==4: Success$ +^\[main\.assertion\.1\] .* assertion y==5: Success$ +-- +^warning: ignoring From e5b9fda8c49d4b6b68da001a0fd9b80a5e945e95 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 3 Apr 2017 11:46:46 +0100 Subject: [PATCH 121/342] Added sound support for opaque functions Currently just havocs the domain if an unknown function is called. --- .../sensitivity-function-call-opaque/main.c | 16 ++++++++++++++++ .../sensitivity-function-call-opaque/test.desc | 10 ++++++++++ .../variable_sensitivity_domain.cpp | 6 +++--- 3 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 regression/goto-analyzer/sensitivity-function-call-opaque/main.c create mode 100644 regression/goto-analyzer/sensitivity-function-call-opaque/test.desc diff --git a/regression/goto-analyzer/sensitivity-function-call-opaque/main.c b/regression/goto-analyzer/sensitivity-function-call-opaque/main.c new file mode 100644 index 00000000000..c207239979a --- /dev/null +++ b/regression/goto-analyzer/sensitivity-function-call-opaque/main.c @@ -0,0 +1,16 @@ +#include + +int opaque(int other, int* side_effect); + +int main(int argc, char *argv[]) +{ + int x=3; + int y=4; + int z=bar(x+1, &y); + + assert(x==3); // Success + assert(y==4); // Unknown - the opaque function could have modified it + assert(z==0); // Unknown - the opaque function could have returned anything + + return 0; +} diff --git a/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc b/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc new file mode 100644 index 00000000000..800243c250b --- /dev/null +++ b/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc @@ -0,0 +1,10 @@ +CORE +main.c +--variable --pointers --arrays --structs --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main\.assertion\.1\] file main.c .* assertion x==3: Unknown$ +^\[main\.assertion\.2\] file main.c .* assertion y==4: Unknown$ +^\[main\.assertion\.3\] file main.c .* assertion z==0: Unknown$ +-- +^warning: ignoring diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 288fb78d865..65545d43b60 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -135,7 +135,7 @@ void variable_sensitivity_domaint::transform( } else { - assert(false); + abstract_state.havoc("opaque function call"); } } else @@ -166,8 +166,8 @@ void variable_sensitivity_domaint::transform( } else { - // unresolved call - assert(false); + assert(to==next); + abstract_state.havoc("unknown opaque function call"); } break; } From 780c534fcb09e8abb41854bf76eb0b0c9490a218 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 3 Apr 2017 15:11:41 +0100 Subject: [PATCH 122/342] Adding reasonable behaviour for opqaue function calls When we have a function call without a body, we could set everything to top (this would be more correct). To keep consistent, we default at the moment to the more reasonable, less sound behaviour of only topping pointers passed in and the return value. Updated the test description to now be able to validate the simple assert. --- .../test.desc | 2 +- .../variable_sensitivity_domain.cpp | 48 +++++++++++++++---- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc b/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc index 800243c250b..8535727e9ba 100644 --- a/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc @@ -3,7 +3,7 @@ main.c --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] file main.c .* assertion x==3: Unknown$ +^\[main\.assertion\.1\] file main.c .* assertion x==3: Success$ ^\[main\.assertion\.2\] file main.c .* assertion y==4: Unknown$ ^\[main\.assertion\.3\] file main.c .* assertion z==0: Unknown$ -- diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 65545d43b60..61e5c2caa06 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -12,6 +12,7 @@ Date: April 2016 #include #include +#include #include "variable_sensitivity_domain.h" #include @@ -120,6 +121,14 @@ void variable_sensitivity_domaint::transform( const symbol_exprt &symbol_expr=to_symbol_expr(function); const irep_idt function_id=symbol_expr.get_identifier(); + // parameters of called function + const symbolt &symbol=ns.lookup(function_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(); + if(to==next) { @@ -135,21 +144,39 @@ void variable_sensitivity_domaint::transform( } else { - abstract_state.havoc("opaque function call"); + if(0) // Sound on opaque function calls + { + abstract_state.havoc("opaque function call"); + } + else + { + for(const exprt &called_arg : arguments) + { + if(called_arg.type().id()==ID_pointer) + { + sharing_ptrt pointer_value= + std::dynamic_pointer_cast( + abstract_state.eval(called_arg, ns)); + + assert(pointer_value); + + // Write top to the pointer + pointer_value->write_dereference( + abstract_state, + ns, + std::stack(), + abstract_state.abstract_object_factory( + called_arg.type().subtype(), ns, true), false); + + + } + } + } } } else { // we have an actual call - - // parameters of called function - const symbolt &symbol=ns.lookup(function_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(); - code_typet::parameterst::const_iterator p_it=parameters.begin(); for(const auto &arg : arguments) { @@ -183,6 +210,7 @@ void variable_sensitivity_domaint::transform( for(const auto ¶m : type.parameters()) { + // Bottom the arguments to the function abstract_state.assign( symbol_exprt(param.get_identifier(), param.type()), abstract_state.abstract_object_factory(param.type(), ns, true, false), From d40c459cdcab06739653116851efe7897ed8047b Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 3 Apr 2017 15:56:40 +0100 Subject: [PATCH 123/342] Moved the function call handling into a separate method for readability --- .../variable_sensitivity_domain.cpp | 243 +++++++++++------- .../variable_sensitivity_domain.h | 8 + 2 files changed, 164 insertions(+), 87 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 61e5c2caa06..0d878b09f20 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -109,93 +109,7 @@ void variable_sensitivity_domaint::transform( case FUNCTION_CALL: { - 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) - { - // called function identifier - const symbol_exprt &symbol_expr=to_symbol_expr(function); - const irep_idt function_id=symbol_expr.get_identifier(); - - // parameters of called function - const symbolt &symbol=ns.lookup(function_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(); - - - if(to==next) - { - if(function_id==CPROVER_PREFIX "set_must" || - function_id==CPROVER_PREFIX "get_must" || - function_id==CPROVER_PREFIX "set_may" || - function_id==CPROVER_PREFIX "get_may" || - function_id==CPROVER_PREFIX "cleanup" || - function_id==CPROVER_PREFIX "clear_may" || - function_id==CPROVER_PREFIX "clear_must") - { - // no effect on constants - } - else - { - if(0) // Sound on opaque function calls - { - abstract_state.havoc("opaque function call"); - } - else - { - for(const exprt &called_arg : arguments) - { - if(called_arg.type().id()==ID_pointer) - { - sharing_ptrt pointer_value= - std::dynamic_pointer_cast( - abstract_state.eval(called_arg, ns)); - - assert(pointer_value); - - // Write top to the pointer - pointer_value->write_dereference( - abstract_state, - ns, - std::stack(), - abstract_state.abstract_object_factory( - called_arg.type().subtype(), ns, true), false); - - - } - } - } - } - } - else - { - // we have an actual call - code_typet::parameterst::const_iterator p_it=parameters.begin(); - for(const auto &arg : arguments) - { - if(p_it==parameters.end()) - break; - - const symbol_exprt parameter_expr(p_it->get_identifier(), arg.type()); - abstract_object_pointert param_val=abstract_state.eval(arg, ns); - abstract_state.assign(parameter_expr, param_val, ns); - - ++p_it; - } - } - } - else - { - assert(to==next); - abstract_state.havoc("unknown opaque function call"); - } + transform_function_call(from, to, ai, ns); break; } @@ -490,3 +404,158 @@ bool variable_sensitivity_domaint::ai_simplify_lhs( else return true; } + +/*******************************************************************\ + +Function: variable_sensitivity_domaint::transform_function_call + + Inputs: + from - the location to transform from which is a function call + to - the destination of the transform (potentially inside the function call) + ai - the abstract interpreter + ns - the namespace of the current state + + Outputs: + + Purpose: Used by variable_sensitivity_domaint::transform to handle + FUNCTION_CALL transforms. This is copying the values of the arguments + into new symbols corresponding to the declared parameter names. + + If the function call is opaque we currently top the return value + and the value of any things whose address is passed into the function. + +\*******************************************************************/ + +void variable_sensitivity_domaint::transform_function_call( + locationt from, locationt to, ai_baset &ai, const namespacet &ns) +{ + assert(from->type==FUNCTION_CALL); + + const code_function_callt &function_call=to_code_function_call(from->code); + const exprt &function=function_call.function(); + + const locationt next=std::next(from); + + if(function.id()==ID_symbol) + { + // called function identifier + const symbol_exprt &symbol_expr=to_symbol_expr(function); + const irep_idt function_id=symbol_expr.get_identifier(); + + const code_function_callt::argumentst &called_arguments= + function_call.arguments(); + + if(to==next) + { + if(ignore_function_call_transform(function_id)) + { + return; + } + + if(0) // Sound on opaque function calls + { + abstract_state.havoc("opaque function call"); + } + else + { + // For any parameter that is a pointer, top the value it is pointing + // at. + for(const exprt &called_arg : called_arguments) + { + if(called_arg.type().id()==ID_pointer) + { + sharing_ptrt pointer_value= + std::dynamic_pointer_cast( + abstract_state.eval(called_arg, ns)); + + assert(pointer_value); + + // Write top to the pointer + pointer_value->write_dereference( + abstract_state, + ns, + std::stack(), + abstract_state.abstract_object_factory( + called_arg.type().subtype(), ns, true), false); + } + } + // TODO (tkiley): Should also top anything globally accessible + } + } + else + { + // we have an actual call + const symbolt &symbol=ns.lookup(function_id); + const code_typet &code_type=to_code_type(symbol.type); + const code_typet::parameterst &declaration_parameters= + code_type.parameters(); + + code_typet::parameterst::const_iterator parameter_it= + declaration_parameters.begin(); + + for(const exprt &called_arg : called_arguments) + { + if(parameter_it==declaration_parameters.end()) + { + // TODO(tkiley): Here we have fewer parameters in the function + // declaration than we had arguments in the function call + // I think this should be an error rather than silently failing? + break; + } + + // Evaluate the expression that is being + // passed into the function call (called_arg) + abstract_object_pointert param_val=abstract_state.eval(called_arg, ns); + + // Assign the evaluated value to the symbol associated with the + // parameter of the function + const symbol_exprt parameter_expr( + parameter_it->get_identifier(), called_arg.type()); + abstract_state.assign(parameter_expr, param_val, ns); + + ++parameter_it; + } + + // TODO(tkiley): Here there were more declared parameters than were passed + // could this be a varadics thing or is this an error? + if(parameter_it!=declaration_parameters.end()) + {} + } + } + else + { + assert(to==next); + abstract_state.havoc("unknown opaque function call"); + } +} + +/*******************************************************************\ + +Function: variable_sensitivity_domaint::ignore_function_call_transform + + Inputs: + function_id - the name of the function being called + + Outputs: Returns true if the function should be ignored + + Purpose: Used to specify which CPROVER internal functions should be skipped + over when doing function call transforms + +\*******************************************************************/ + +bool variable_sensitivity_domaint::ignore_function_call_transform( + const irep_idt &function_id) const +{ + static const std::set ignored_internal_function={ + CPROVER_PREFIX "set_must", + CPROVER_PREFIX "get_must", + CPROVER_PREFIX "set_may", + CPROVER_PREFIX "get_may", + CPROVER_PREFIX "cleanup", + CPROVER_PREFIX "clear_may", + CPROVER_PREFIX "clear_must" + }; + + return ignored_internal_function.find(function_id)!= + ignored_internal_function.cend(); +} diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 2e685c527cf..0590e00474d 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -109,6 +109,14 @@ class variable_sensitivity_domaint:public ai_domain_baset const namespacet &ns) const override; private: + void transform_function_call( + locationt from, + locationt to, + ai_baset &ai, + const namespacet &ns); + + bool ignore_function_call_transform(const irep_idt &function_id) const; + abstract_environmentt abstract_state; }; From fcbc70d4e53e07e8ca2d0ea64a58f8faec9df68c Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 3 Apr 2017 17:32:42 +0100 Subject: [PATCH 124/342] Support for topping the global values --- .../sensitivity-function-call-opaque/main.c | 6 ++++++ .../sensitivity-function-call-opaque/test.desc | 1 + .../variable_sensitivity_domain.cpp | 13 ++++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/regression/goto-analyzer/sensitivity-function-call-opaque/main.c b/regression/goto-analyzer/sensitivity-function-call-opaque/main.c index c207239979a..7a370b56c4b 100644 --- a/regression/goto-analyzer/sensitivity-function-call-opaque/main.c +++ b/regression/goto-analyzer/sensitivity-function-call-opaque/main.c @@ -1,16 +1,22 @@ #include +int global_value; + int opaque(int other, int* side_effect); int main(int argc, char *argv[]) { int x=3; int y=4; + + global_value=4; + int z=bar(x+1, &y); assert(x==3); // Success assert(y==4); // Unknown - the opaque function could have modified it assert(z==0); // Unknown - the opaque function could have returned anything + assert(global_value==4); // Unknown - the opaque function could have modified this return 0; } diff --git a/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc b/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc index 8535727e9ba..5302bc865d5 100644 --- a/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc @@ -6,5 +6,6 @@ main.c ^\[main\.assertion\.1\] file main.c .* assertion x==3: Success$ ^\[main\.assertion\.2\] file main.c .* assertion y==4: Unknown$ ^\[main\.assertion\.3\] file main.c .* assertion z==0: Unknown$ +^\[main\.assertion\.4\] file main.c .* assertion global_value==4: Unknown$ -- ^warning: ignoring diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 0d878b09f20..9ca6b2dd087 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -479,7 +479,18 @@ void variable_sensitivity_domaint::transform_function_call( called_arg.type().subtype(), ns, true), false); } } - // TODO (tkiley): Should also top anything globally accessible + + // Top any global values + for(const auto &symbol : ns.get_symbol_table().symbols) + { + if(!symbol.second.is_procedure_local()) + { + abstract_state.assign( + symbol_exprt(symbol.first, symbol.second.type), + abstract_state.abstract_object_factory(symbol.second.type, ns, true), + ns); + } + } } } else From 30f7e6426c0db490a58595622c958ed6d0d881f1 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 13 Apr 2017 12:24:34 +0100 Subject: [PATCH 125/342] Assertion for varags When the parmeters and the arguments don't match, either the function was called with too many args (in which case the function must be variadic) or too few, in which case the code isn't valid. Added appropriate assertions and a test for a variadic function. --- .../sensitivity-function-call-varargs/main.c | 26 +++++++++++++++++++ .../test.desc | 9 +++++++ .../variable_sensitivity_domain.cpp | 10 +++---- 3 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 regression/goto-analyzer/sensitivity-function-call-varargs/main.c create mode 100644 regression/goto-analyzer/sensitivity-function-call-varargs/test.desc diff --git a/regression/goto-analyzer/sensitivity-function-call-varargs/main.c b/regression/goto-analyzer/sensitivity-function-call-varargs/main.c new file mode 100644 index 00000000000..1f35e93715f --- /dev/null +++ b/regression/goto-analyzer/sensitivity-function-call-varargs/main.c @@ -0,0 +1,26 @@ +#include +#include + +int bar(int size, ...) +{ + int total=0; + va_list args; + va_start(args, size); + for(int i = 0; i < size; ++i) + { + int val = va_arg(args, int); + total+=val; + } + + va_end(args); + return total; +} + +int main(int argc, char *argv[]) +{ + int y=bar(4, 1, 2, 2, 1); + assert(y==6); + + int z=bar(0); + assert(z==0); +} diff --git a/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc b/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc new file mode 100644 index 00000000000..c75fb1d3837 --- /dev/null +++ b/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc @@ -0,0 +1,9 @@ +CORE +main.c +--variable --pointers --arrays --structs --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main\.assertion\.1\] .* assertion y==6: Unknown$ +^\[main\.assertion\.2\] .* assertion z==0: Unknown$ +-- +^warning: ignoring diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 9ca6b2dd087..02dd6554509 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -508,9 +508,7 @@ void variable_sensitivity_domaint::transform_function_call( { if(parameter_it==declaration_parameters.end()) { - // TODO(tkiley): Here we have fewer parameters in the function - // declaration than we had arguments in the function call - // I think this should be an error rather than silently failing? + assert(code_type.has_ellipsis()); break; } @@ -527,10 +525,8 @@ void variable_sensitivity_domaint::transform_function_call( ++parameter_it; } - // TODO(tkiley): Here there were more declared parameters than were passed - // could this be a varadics thing or is this an error? - if(parameter_it!=declaration_parameters.end()) - {} + // Too few arguments so invalid code + assert(parameter_it==declaration_parameters.end()); } } else From 96677253b1976632be8e6885ec73a5334ea694e6 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 15 Jun 2017 14:01:29 +0100 Subject: [PATCH 126/342] Made ai_simplify perform a partial simplifcation If the ai_simplify is not able to resolve the expression to a constant, it tries to simplify recursively any child operations. For example, given a int i that is know to be 1, and an unknown (top) array a, it would convert a[i] to a[1]. --- regression/goto-analyzer-simplify/Makefile | 31 +++++++++++++++++++ regression/goto-analyzer-simplify/chain.sh | 14 +++++++++ .../partial-simplify-array/main.c | 7 +++++ .../partial-simplify-array/test.desc | 5 +++ .../variable_sensitivity_domain.cpp | 14 +++++++-- 5 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 regression/goto-analyzer-simplify/Makefile create mode 100755 regression/goto-analyzer-simplify/chain.sh create mode 100644 regression/goto-analyzer-simplify/partial-simplify-array/main.c create mode 100644 regression/goto-analyzer-simplify/partial-simplify-array/test.desc diff --git a/regression/goto-analyzer-simplify/Makefile b/regression/goto-analyzer-simplify/Makefile new file mode 100644 index 00000000000..08fe97ae88c --- /dev/null +++ b/regression/goto-analyzer-simplify/Makefile @@ -0,0 +1,31 @@ + +default: tests.log + +test: + @if ! ../test.pl -c ../chain.sh ; then \ + ../failed-tests-printer.pl ; \ + exit 1; \ + fi + +tests.log: + @if ! ../test.pl -c ../chain.sh ; then \ + ../failed-tests-printer.pl ; \ + exit 1; \ + fi + +show: + @for dir in *; do \ + if [ -d "$$dir" ]; then \ + vim -o "$$dir/*.c" "$$dir/*.out"; \ + fi; \ + done; + +clean: + @for dir in *; do \ + rm -f tests.log; \ + if [ -d "$$dir" ]; then \ + cd "$$dir"; \ + rm -f *.out *.gb; \ + cd ..; \ + fi \ + done diff --git a/regression/goto-analyzer-simplify/chain.sh b/regression/goto-analyzer-simplify/chain.sh new file mode 100755 index 00000000000..5fbf28733ed --- /dev/null +++ b/regression/goto-analyzer-simplify/chain.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +src_dir=../../../src + +goto_analyzer=$src_dir/goto-analyzer/goto-analyzer + +options=$1 +file_name=${2%.c} + +echo options: $options +echo file name : $file_name + +$goto_analyzer $file_name.c $options --simplify $file_name_simp.out +$goto_analyzer $file_name_simp.out --show-goto-functions diff --git a/regression/goto-analyzer-simplify/partial-simplify-array/main.c b/regression/goto-analyzer-simplify/partial-simplify-array/main.c new file mode 100644 index 00000000000..dce6dd9de42 --- /dev/null +++ b/regression/goto-analyzer-simplify/partial-simplify-array/main.c @@ -0,0 +1,7 @@ +extern int arr[]; + +void main() +{ + int index=0; + int j=arr[index]; +} diff --git a/regression/goto-analyzer-simplify/partial-simplify-array/test.desc b/regression/goto-analyzer-simplify/partial-simplify-array/test.desc new file mode 100644 index 00000000000..e5a2885215a --- /dev/null +++ b/regression/goto-analyzer-simplify/partial-simplify-array/test.desc @@ -0,0 +1,5 @@ +CORE +main.c +"--variable --arrays" + +arr\[0l\] diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 02dd6554509..2f974546a48 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -295,8 +295,18 @@ 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 true; + if(c.id()==ID_nil) + { + bool no_simplification=true; + + // Try to simplify recursively any child operations + for(exprt &op : condition.operands()) + { + no_simplification&=ai_simplify(op, ns); + } + + return no_simplification; + } else { bool condition_changed=(condition!=c); From a91626e871e0fa820a1e57308d3ed5d7c926bc4b Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 27 Jun 2017 13:43:35 +0100 Subject: [PATCH 127/342] Corrected lhs simplification True means no simplification has occured so this should be reflected in the lhs simplification --- .../variable_sensitivity_domain.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 2f974546a48..8b7d3a3cd54 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -374,27 +374,27 @@ bool variable_sensitivity_domaint::ai_simplify_lhs( { index_exprt ie = to_index_expr(condition); exprt index = ie.index(); - bool changed = ai_simplify(index, ns); - if(changed) + bool no_simplification=ai_simplify(index, ns); + if(!no_simplification) { ie.index() = index; condition = simplify_expr(ie, ns); } - return !changed; + return no_simplification; } else if(condition.id()==ID_dereference) { dereference_exprt de = to_dereference_expr(condition); exprt pointer = de.pointer(); - bool changed = ai_simplify(pointer, ns); - if(changed) + bool no_simplification = ai_simplify(pointer, ns); + if(!no_simplification) { de.pointer() = pointer; condition = simplify_expr(de, ns); // So *(&x) -> x } - return !changed; + return no_simplification; } else if(condition.id()==ID_member) { @@ -402,14 +402,14 @@ 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_lhs(compound, ns); - if(changed) + bool no_simplification = ai_simplify_lhs(compound, ns); + if(!no_simplification) { me.compound() = compound; condition = simplify_expr(me, ns); } - return !changed; + return no_simplification; } else return true; From 9b10dd8ff8a7b51008da4e7bd8fb2100c530426c Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 27 Jun 2017 14:02:56 +0100 Subject: [PATCH 128/342] Adding tests for simplification of lhs --- .../simplify-lhs-array-index/main.c | 15 +++++++ .../simplify-lhs-array-index/test.desc | 7 ++++ .../simplify-lhs-array-pointers-index/main.c | 33 +++++++++++++++ .../test.desc | 8 ++++ .../simplify-lhs-dereference/main.c | 23 ++++++++++ .../simplify-lhs-dereference/test.desc | 6 +++ .../simplify-lhs-member/main.c | 42 +++++++++++++++++++ .../simplify-lhs-member/test.desc | 8 ++++ .../main.c | 21 ++++++++++ .../test.desc | 6 +++ 10 files changed, 169 insertions(+) create mode 100644 regression/goto-analyzer-simplify/simplify-lhs-array-index/main.c create mode 100644 regression/goto-analyzer-simplify/simplify-lhs-array-index/test.desc create mode 100644 regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/main.c create mode 100644 regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/test.desc create mode 100644 regression/goto-analyzer-simplify/simplify-lhs-dereference/main.c create mode 100644 regression/goto-analyzer-simplify/simplify-lhs-dereference/test.desc create mode 100644 regression/goto-analyzer-simplify/simplify-lhs-member/main.c create mode 100644 regression/goto-analyzer-simplify/simplify-lhs-member/test.desc create mode 100644 regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/main.c create mode 100644 regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/test.desc diff --git a/regression/goto-analyzer-simplify/simplify-lhs-array-index/main.c b/regression/goto-analyzer-simplify/simplify-lhs-array-index/main.c new file mode 100644 index 00000000000..2c22f8b87a1 --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-lhs-array-index/main.c @@ -0,0 +1,15 @@ +void main() +{ + int arr[4] = {1, 2, 3, 4}; + + // No simplification + arr[0] = 1; + + // Can simplify + int constant = 1; + arr[constant] = 2; + + // No simplification + int nondet; + arr[nondet] = 3; +} diff --git a/regression/goto-analyzer-simplify/simplify-lhs-array-index/test.desc b/regression/goto-analyzer-simplify/simplify-lhs-array-index/test.desc new file mode 100644 index 00000000000..f5a352cbd09 --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-lhs-array-index/test.desc @@ -0,0 +1,7 @@ +CORE +main.c +"--variable --arrays" + +arr\[0l\] = +arr\[1l\] = +arr\[\(signed long int\)nondet\] = diff --git a/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/main.c b/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/main.c new file mode 100644 index 00000000000..8883f03521e --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/main.c @@ -0,0 +1,33 @@ +void main() +{ + int symbol_a; + int symbol_b; + + int nondet; + int * nondet_pointer; + if(nondet > 0) + { + nondet_pointer = &symbol_a; + } + else + { + nondet_pointer = &symbol_b; + } + + int *arr[] = { &symbol_a, &symbol_b, nondet_pointer }; + + // Simplify the pointer + *arr[0] = 1; + + // Simplify index and the pointer + int constant1 = 1; + *arr[constant1] = 2; + + // Simplify the index but not the pointer + int constant2 = 2; + *arr[constant2] = 3; + + // No simplification + int nondet_index; + *arr[nondet_index] = 4; +} diff --git a/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/test.desc b/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/test.desc new file mode 100644 index 00000000000..8e3526b73e5 --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +"--variable --arrays --pointers" + +symbol_a = 1 +symbol_b = 2 +\*arr\[2l\] = 3; +\*arr\[\(signed long int\)nondet_index\] = 4; diff --git a/regression/goto-analyzer-simplify/simplify-lhs-dereference/main.c b/regression/goto-analyzer-simplify/simplify-lhs-dereference/main.c new file mode 100644 index 00000000000..26a245a56f2 --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-lhs-dereference/main.c @@ -0,0 +1,23 @@ +void main() +{ + int symbol; + + int *pointer=&symbol; + + // Simplify + *pointer=5; + + int nondet; + if(nondet>0) + { + pointer=&nondet; + } + else + { + pointer=&symbol; + } + + // No simplification + *pointer=6; + +} diff --git a/regression/goto-analyzer-simplify/simplify-lhs-dereference/test.desc b/regression/goto-analyzer-simplify/simplify-lhs-dereference/test.desc new file mode 100644 index 00000000000..8fcfb8fce7d --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-lhs-dereference/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +"--variable --pointers" + +symbol = 5 +\*pointer = 6 diff --git a/regression/goto-analyzer-simplify/simplify-lhs-member/main.c b/regression/goto-analyzer-simplify/simplify-lhs-member/main.c new file mode 100644 index 00000000000..7889998318e --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-lhs-member/main.c @@ -0,0 +1,42 @@ +struct test_struct +{ + int * pointer_component; + int array[5]; +}; + +void main() +{ + int symbol; + + struct test_struct value; + + // Simplify a pointer inside a struct + int symbol; + value.pointer_component=&symbol; + + // Simplify + *value.pointer_component=5; + + int nondet; + if(nondet>0) + { + value.pointer_component=&nondet; + } + else + { + value.pointer_component=&symbol; + } + + // No simplification + *value.pointer_component=6; + + // Simplify an array + + // Can simplify + int constant = 1; + value.array[constant] = 2; + + // No simplification + int nondet; + value.array[nondet] = 3; +} diff --git a/regression/goto-analyzer-simplify/simplify-lhs-member/test.desc b/regression/goto-analyzer-simplify/simplify-lhs-member/test.desc new file mode 100644 index 00000000000..be66617cabb --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-lhs-member/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +"--variable --arrays --pointers --structs" + +symbol = 5 +\*value\.pointer_component = 6 +value\.array\[1l\] = 2 +value\.array\[\(signed long int\)nondet\] = 3 diff --git a/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/main.c b/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/main.c new file mode 100644 index 00000000000..a7e9b0d950e --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/main.c @@ -0,0 +1,21 @@ +void main() +{ + int array[] = {1, 2, 3, 4, 5}; + + int *pointer=array; + + // Simplify -> array[0] = 5 + *pointer=5; + + int nondet; + pointer[nondet]=6; + + // TODO: Currently writing to an offset pointer sets the domain to top + // so recreate the variables to reign the domain back in + // This will be addressed by diffblue/cbmc-toyota#118 + int new_array[] = {1, 2, 3, 4, 5}; + int * new_pointer=new_array; + + int constant=1; + new_pointer[constant]=7; +} diff --git a/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/test.desc b/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/test.desc new file mode 100644 index 00000000000..00a90ef4e9d --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +"--variable --arrays --pointers" +array\[0l\] = 5 +array\[\(signed long int\)nondet\] = 6 +new_array\[1l\] = 7 From 6c65dbccc9e8b01a804d62cab88c2bb32f25bfe8 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 27 Jun 2017 15:19:24 +0100 Subject: [PATCH 129/342] Fixed constant propogation test An additional assign is simplified as the LHS side simplification now works. --- regression/goto-analyzer/constant_propagation_11/test.desc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/regression/goto-analyzer/constant_propagation_11/test.desc b/regression/goto-analyzer/constant_propagation_11/test.desc index 8c5f8a279be..4bc8b249535 100644 --- a/regression/goto-analyzer/constant_propagation_11/test.desc +++ b/regression/goto-analyzer/constant_propagation_11/test.desc @@ -4,5 +4,7 @@ main.c ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 1: SUCCESS$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 6, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 9, function calls: 2$ -- ^warning: ignoring From 603e08fb516c7ab74baf33897bb552da4ae0343d Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 27 Jun 2017 18:23:09 +0100 Subject: [PATCH 130/342] Corrected code in base class and removed duplicate code --- .../variable_sensitivity_domain.cpp | 67 ------------------- .../variable_sensitivity_domain.h | 4 -- 2 files changed, 71 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 8b7d3a3cd54..0a3707cc20e 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -350,73 +350,6 @@ bool variable_sensitivity_domaint::is_top() const /*******************************************************************\ -Function: variable_sensitivity_domaint::ai_simplify_lhs - - Inputs: - condition - the expression to simplify - ns - the namespace - - 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 - 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 no_simplification=ai_simplify(index, ns); - if(!no_simplification) - { - ie.index() = index; - condition = simplify_expr(ie, ns); - } - - return no_simplification; - } - else if(condition.id()==ID_dereference) - { - dereference_exprt de = to_dereference_expr(condition); - exprt pointer = de.pointer(); - bool no_simplification = ai_simplify(pointer, ns); - if(!no_simplification) - { - de.pointer() = pointer; - condition = simplify_expr(de, ns); // So *(&x) -> x - } - - return no_simplification; - } - else if(condition.id()==ID_member) - { - member_exprt me = to_member_expr(condition); - exprt compound = me.compound(); - // Carry on the RHS since we still require an addressable object for the - // struct - bool no_simplification = ai_simplify_lhs(compound, ns); - if(!no_simplification) - { - me.compound() = compound; - condition = simplify_expr(me, ns); - } - - return no_simplification; - } - else - return true; -} - -/*******************************************************************\ - Function: variable_sensitivity_domaint::transform_function_call Inputs: diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 0590e00474d..d901791f767 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -104,10 +104,6 @@ class variable_sensitivity_domaint:public ai_domain_baset bool is_bottom() const override; bool is_top() const override; - bool ai_simplify_lhs( - exprt &condition, - const namespacet &ns) const override; - private: void transform_function_call( locationt from, From bb6ed40a204e917f51dee72376b62fbf5f360e72 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 11 Jul 2017 14:54:59 +0100 Subject: [PATCH 131/342] Implementing a write_stack to represent writing to a addressable location Deals with storing a stack to write to things like: &a[1] &s.comp &a[x] + 1 By building a stack as parsing the expression tree. It does not support pointer arithmetic outside the scope of an array (e.g. within a struct) This will be used to store pointer values. Disabled unit tests since don't have the prerequistes in this branch --- src/analyses/Makefile | 2 + .../variable-sensitivity/write_stack.cpp | 260 +++++++++ .../variable-sensitivity/write_stack.h | 66 +++ .../write_stack_entry.cpp | 79 +++ .../variable-sensitivity/write_stack_entry.h | 57 ++ unit/Makefile | 1 + .../variable-sensitivity/write_stack.cpp | 522 ++++++++++++++++++ 7 files changed, 987 insertions(+) create mode 100644 src/analyses/variable-sensitivity/write_stack.cpp create mode 100644 src/analyses/variable-sensitivity/write_stack.h create mode 100644 src/analyses/variable-sensitivity/write_stack_entry.cpp create mode 100644 src/analyses/variable-sensitivity/write_stack_entry.h create mode 100644 unit/analyses/variable-sensitivity/write_stack.cpp diff --git a/src/analyses/Makefile b/src/analyses/Makefile index f1975f646a0..0fbf7111f5a 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -46,6 +46,8 @@ SRC = ai.cpp \ variable-sensitivity/full_struct_abstract_object.cpp \ variable-sensitivity/constant_array_abstract_object.cpp \ variable-sensitivity/union_abstract_object.cpp \ + variable-sensitivity/write_stack.cpp \ + variable-sensitivity/write_stack_entry.cpp \ # Empty last line INCLUDES= -I .. diff --git a/src/analyses/variable-sensitivity/write_stack.cpp b/src/analyses/variable-sensitivity/write_stack.cpp new file mode 100644 index 00000000000..7f9185c631f --- /dev/null +++ b/src/analyses/variable-sensitivity/write_stack.cpp @@ -0,0 +1,260 @@ +/*******************************************************************\ + + Module: Variable Sensitivity Domain + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +/// \file +/// Represents a stack of write operations to an addressable memory +/// location + +#include "write_stack.h" + +#include + +#include +#include + +/// Build a topstack +write_stackt::write_stackt(): + stack(), + top_stack(true) +{} + +/// Construct a write stack from an expression +/// \param expr: The expression to represent +/// \param environment: The environment to evaluate any expressions in +/// \param ns: The global namespace +write_stackt::write_stackt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) +{ + top_stack=false; + if(expr.type().id()==ID_array) + { + // We are assigning an array to a pointer, which is equivalent to assigning + // the first element of that arary + // &(expr)[0] + construct_stack_to_pointer( + address_of_exprt( + index_exprt( + expr, constant_exprt::integer_constant(0))), environment, ns); + } + else + { + construct_stack_to_pointer(expr, environment, ns); + } +} + +/// Add to the stack the elements to get to a pointer +/// \param expr: An expression of type pointer to construct the stack to +/// \param environment: The environment to evaluate any expressions in +/// \param ns: The global namespace +void write_stackt::construct_stack_to_pointer( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) +{ + PRECONDITION(expr.type().id()==ID_pointer); + + // If we are a pointer to a struct, we do not currently support reading + // writing directly to it so just create a top stack + if(ns.follow(expr.type().subtype()).id()==ID_struct) + { + top_stack=true; + return; + } + + if(expr.id()==ID_address_of) + { + // resovle reminder, can either be a symbol, member or index of + // otherwise unsupported + construct_stack_to_lvalue(expr.op0(), environment, ns); + } + else if(expr.id()==ID_plus || expr.id()==ID_minus) + { + exprt base; + exprt offset; + const integral_resultt &which_side= + get_which_side_integral(expr, base, offset); + INVARIANT( + which_side!=integral_resultt::NEITHER_INTEGRAL, + "An offset must be an integral amount"); + + if(expr.id()==ID_minus) + { + // can't get a valid pointer by subtracting from a constant number + if(which_side==integral_resultt::LHS_INTEGRAL) + { + top_stack=true; + return; + } + offset.negate(); + } + + abstract_object_pointert offset_value=environment.eval(offset, ns); + + add_to_stack( + std::make_shared(offset_value), environment, ns); + + // Build the pointer part + construct_stack_to_pointer(base, environment, ns); + + if(!top_stack) + { + // check the top of the stack is pointing at an array - we don't support + // offset apart from within arrays + std::shared_ptr entry= + *std::prev(stack.cend()); + if(entry->get_access_expr().type().id()!=ID_array) + { + top_stack=true; + } + } + } + else + { + // unknown expression type - play it safe and set to top + top_stack=true; + } +} + +/// Construct a stack up to a specific l-value (i.e. symbol or position in an +/// array or struct) +/// \param expr: The expression representing a l-value +/// \param environment: The environment to evaluate any expressions in +/// \param ns: The global namespace +void write_stackt::construct_stack_to_lvalue( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) +{ + if(!top_stack) + { + if(expr.id()==ID_member) + { + add_to_stack(std::make_shared(expr), environment, ns); + construct_stack_to_lvalue(expr.op0(), environment, ns); + } + else if(expr.id()==ID_symbol) + { + add_to_stack(std::make_shared(expr), environment, ns); + } + else if(expr.id()==ID_index) + { + construct_stack_to_array_index(to_index_expr(expr), environment, ns); + } + else + { + top_stack=true; + } + } +} + +/// Construct a stack for an array position l-value. +/// \param index_expr: The index expression to construct to. +/// \param environment: The environment to evaluate any expressions in +/// \param ns: The global namespace +void write_stackt::construct_stack_to_array_index( + const index_exprt &index_expr, + const abstract_environmentt &environment, + const namespacet &ns) +{ + abstract_object_pointert offset_value= + environment.eval(index_expr.index(), ns); + + add_to_stack(std::make_shared(offset_value), environment, ns); + construct_stack_to_lvalue(index_expr.array(), environment, ns); +} + +/// Convert the stack to an expression that can be used to write to. +/// \return The expression representing the stack, with nil_exprt expressions +/// for top elements. +exprt write_stackt::to_expression() const +{ + exprt access_expr=nil_exprt(); + for(const std::shared_ptr &entry : stack) + { + exprt new_expr=entry->get_access_expr(); + if(access_expr.id()==ID_nil) + { + access_expr=new_expr; + } + else + { + if(new_expr.operands().size()==0) + { + new_expr.operands().resize(1); + } + new_expr.op0()=access_expr; + + access_expr=new_expr; + } + } + address_of_exprt top_expr(access_expr); + return top_expr; +} + +/// Is the stack representing an unknown value and hence can't be written to +/// or read from. +/// \return True if the stack is top. +bool write_stackt::is_top_value() const +{ + return top_stack; +} + +/// Add an element to the top of the stack. This will squash in with the top +/// element if possible. +/// \param entry_pointer: The new element for the stack. +/// \param environment: The environment to evaluate any expressions in +/// \param ns: The global namespace +void write_stackt::add_to_stack( + std::shared_ptr entry_pointer, + const abstract_environmentt environment, + const namespacet &ns) +{ + if(stack.empty() || + !stack.front()->try_squash_in(entry_pointer, environment, ns)) + { + stack.insert(stack.begin(), entry_pointer); + } +} + +/// Utility function to find out which side of a binary operation has an +/// integral type, if any. +/// \param expr: The (binary) expression to evaluate. +/// \param [out] out_base_expr: The sub-expression which is not integral typed +/// \param [out] out_integral_expr: The subexpression which is integraled typed. +/// \return: An enum specifying whether the integral type is the LHS (op0), +/// RHS (op1) or neither. +write_stackt::integral_resultt + write_stackt::get_which_side_integral( + const exprt &expr, + exprt &out_base_expr, + exprt &out_integral_expr) +{ + PRECONDITION(expr.operands().size()==2); + static const std::unordered_set integral_types= + { ID_signedbv, ID_unsignedbv, ID_integer }; + if(integral_types.find(expr.op0().type().id())!=integral_types.cend()) + { + out_integral_expr=expr.op0(); + out_base_expr=expr.op1(); + return integral_resultt::LHS_INTEGRAL; + } + else if(integral_types.find(expr.op1().type().id())!=integral_types.cend()) + { + out_integral_expr=expr.op1(); + out_base_expr=expr.op0(); + return integral_resultt::RHS_INTEGRAL; + } + else + { + out_integral_expr.make_nil(); + out_base_expr.make_nil(); + return integral_resultt::NEITHER_INTEGRAL; + } +} diff --git a/src/analyses/variable-sensitivity/write_stack.h b/src/analyses/variable-sensitivity/write_stack.h new file mode 100644 index 00000000000..f06983dbcd0 --- /dev/null +++ b/src/analyses/variable-sensitivity/write_stack.h @@ -0,0 +1,66 @@ +/*******************************************************************\ + + Module: Variable Sensitivity Domain + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +/// \file +/// Represents a stack of write operations to an addressable memory +/// location + +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_STACK_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_STACK_H + +#include + +class write_stackt +{ +public: + typedef std::vector> + continuation_stack_storet; + + write_stackt(); + + write_stackt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); + + exprt to_expression() const; + bool is_top_value() const; + +private: + void construct_stack_to_pointer( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); + + void construct_stack_to_lvalue( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); + + void construct_stack_to_array_index( + const index_exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); + + void add_to_stack( + std::shared_ptr entry_pointer, + const abstract_environmentt environment, + const namespacet &ns); + + enum class integral_resultt { LHS_INTEGRAL, RHS_INTEGRAL, NEITHER_INTEGRAL }; + + static integral_resultt get_which_side_integral( + const exprt &expr, + exprt &out_base_expr, + exprt &out_integral_expr); + + continuation_stack_storet stack; + bool top_stack; +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_STACK_H diff --git a/src/analyses/variable-sensitivity/write_stack_entry.cpp b/src/analyses/variable-sensitivity/write_stack_entry.cpp new file mode 100644 index 00000000000..73731e7519d --- /dev/null +++ b/src/analyses/variable-sensitivity/write_stack_entry.cpp @@ -0,0 +1,79 @@ +#include + + +#include + +#include "write_stack_entry.h" + +/// Try to combine a new stack element with the current top of the stack +/// \param new_entry: The new entry to combine with +/// \param enviroment: The enviroment to evalaute things in +/// \param ns: The global namespace +/// \return True if this stack entry and thew new entry were combined +bool write_stack_entryt::try_squash_in( + std::shared_ptr new_entry, + const abstract_environmentt &enviroment, + const namespacet &ns) +{ + return false; +} + +/// Build a simple entry based off a single expression +/// \param expr: The expression being represented +simple_entryt::simple_entryt(exprt expr): + simple_entry(expr) +{ + // Invalid simple expression added to the stack + PRECONDITION(expr.id()==ID_member || expr.id()==ID_symbol); +} + +/// Get the expression part needed to read this stack entry. For simple +/// expressions this is just the expression itself. +/// \return The expression to read this part of the stack +exprt simple_entryt::get_access_expr() const +{ + return simple_entry; +} + +offset_entryt::offset_entryt(abstract_object_pointert offset_value): + offset(offset_value) +{ + // The type of the abstract object should be an integral number + static const std::unordered_set integral_types= + { ID_signedbv, ID_unsignedbv, ID_integer }; + PRECONDITION( + integral_types.find(offset_value->type().id())!=integral_types.cend()); +} + +/// Get the expression part needed to read this stack entry. For offset entries +/// this is an index expression with the index() part the offset +/// \return The expression to read this part of the stack +exprt offset_entryt::get_access_expr() const +{ + return index_exprt(exprt(), offset->to_constant()); +} + +/// Try to combine a new stack element with the current top of the stack. This +/// will succeed if they are both offsets as we can combine these offsets into +/// the sum of the offsets +/// \param new_entry: The new entry to combine with +/// \param enviroment: The enviroment to evalaute things in +/// \param ns: The global namespace +/// \return True if this stack entry and thew new entry were combined +bool offset_entryt::try_squash_in( + std::shared_ptr new_entry, + const abstract_environmentt &enviroment, + const namespacet &ns) +{ + std::shared_ptr cast_entry= + std::dynamic_pointer_cast(new_entry); + if(cast_entry) + { + plus_exprt result_offset( + cast_entry->offset->to_constant(), offset->to_constant()); + offset=enviroment.eval(result_offset, ns); + return true; + } + return false; +} + diff --git a/src/analyses/variable-sensitivity/write_stack_entry.h b/src/analyses/variable-sensitivity/write_stack_entry.h new file mode 100644 index 00000000000..5f35ed15311 --- /dev/null +++ b/src/analyses/variable-sensitivity/write_stack_entry.h @@ -0,0 +1,57 @@ +/*******************************************************************\ + + Module: Analyses Variable Sensitivity + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +/// \file +/// Represents an entry in the write_stackt + +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_STACK_ENTRY_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_STACK_ENTRY_H + +#include +#include + +#include +#include +#include + + +class write_stack_entryt +{ +public: + virtual ~write_stack_entryt() = default; + virtual exprt get_access_expr() const=0; + virtual bool try_squash_in( + std::shared_ptr new_entry, + const abstract_environmentt &enviroment, + const namespacet &ns); +}; + +class simple_entryt:public write_stack_entryt +{ +public: + explicit simple_entryt(exprt expr); + virtual exprt get_access_expr() const override; +private: + exprt simple_entry; +}; + +class offset_entryt:public write_stack_entryt +{ +public: + explicit offset_entryt(abstract_object_pointert offset_value); + virtual exprt get_access_expr() const override; + virtual bool try_squash_in( + std::shared_ptr new_entry, + const abstract_environmentt &enviroment, + const namespacet &ns) override; +private: + abstract_object_pointert offset; +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_STACK_ENTRY_H + diff --git a/unit/Makefile b/unit/Makefile index 758520e9018..138bbe121e3 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -18,6 +18,7 @@ SRC += analyses/ai/ai.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 \ + analyses/variable-sensitivity/write_stack.cpp \ ansi-c/max_malloc_size.cpp \ ansi-c/type2name.cpp \ big-int/big-int.cpp \ diff --git a/unit/analyses/variable-sensitivity/write_stack.cpp b/unit/analyses/variable-sensitivity/write_stack.cpp new file mode 100644 index 00000000000..065202a77a1 --- /dev/null +++ b/unit/analyses/variable-sensitivity/write_stack.cpp @@ -0,0 +1,522 @@ +/*******************************************************************\ + + Module: Write Stack Unit Tests + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +/// \file +/// Unit tests for construction of write stack + +#include "catch.hpp" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#include +#include + + +SCENARIO("Constructing write stacks", + "[core][analyses][variable-sensitivity][continuation-stack]") +{ + 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); + + config.set_arch("none"); + + abstract_environmentt environment; + environment.make_top(); + + c_to_exprt to_expr; + + GIVEN("A int x") + { + typet basic_symbol_type=signedbv_typet(32); + symbol_table.add( + auxiliary_symbolt("x", basic_symbol_type)); + + WHEN("Constructing from &x") + { + exprt in_expr=to_expr("&x", ns); + CAPTURE(expr2c(in_expr, ns)); + + THEN("The constructed stack should be &x") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const exprt &object=out_expr.op0(); + require_exprt::require_symbol(object, "x"); + } + } + } + GIVEN("A int a[5]") + { + typet array_type= + array_typet(signedbv_typet(32), constant_exprt::integer_constant(5)); + symbol_table.add(auxiliary_symbolt("a", array_type)); + + WHEN("Constructing from a") + { + exprt in_expr=to_expr("a", ns); + THEN("The constructed stack should be &a[0]") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const index_exprt &index_expr= + require_exprt::require_index(out_expr.op0(), 0); + require_exprt::require_symbol(index_expr.array(), "a"); + } + } + WHEN("Constructing from &a") + { + exprt in_expr=to_expr("&a", ns); + + THEN("The constructed stack should be &a") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + // TODO: make consistent with above + REQUIRE(out_expr.id()==ID_address_of); + require_exprt::require_symbol(out_expr.op0(), "a"); + } + } + WHEN("Constructing from &a[0]") + { + exprt in_expr=to_expr("&a[0]", ns); + + CAPTURE(expr2c(in_expr, ns)); + THEN("The constructed stack should be &a[0]") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const exprt &object=out_expr.op0(); + const index_exprt &index_expr= + require_exprt::require_index(object, 0); + require_exprt::require_symbol(index_expr.array(), "a"); + } + } + WHEN("Constructing from &a[1]") + { + exprt in_expr=to_expr("&a[1]", ns); + + CAPTURE(expr2c(in_expr, ns)); + THEN("The constructed stack should be &a[1]") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const index_exprt &index_expr= + require_exprt::require_index(out_expr.op0(), 1); + require_exprt::require_symbol(index_expr.array(), "a"); + } + } + WHEN("Constructing from &a[0]+1") + { + exprt in_expr=to_expr("&a[0]+1", ns); + + CAPTURE(expr2c(in_expr, ns)); + THEN("The constructed stack should be &a[1]") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const index_exprt &index_expr= + require_exprt::require_index(out_expr.op0(), 1); + require_exprt::require_symbol(index_expr.array(), "a"); + } + } + WHEN("Constructing from &a[1]+1") + { + exprt in_expr=to_expr("&a[1]+1", ns); + + CAPTURE(expr2c(in_expr, ns)); + + THEN("The constructed stack should be &a[2]") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const index_exprt &index_expr= + require_exprt::require_index(out_expr.op0(), 2); + require_exprt::require_symbol(index_expr.array(), "a"); + } + } + WHEN("Constructing from &a[1]-1") + { + exprt in_expr=to_expr("&a[1]-1", ns); + + CAPTURE(expr2c(in_expr, ns)); + + THEN("The constructed stack should be &a[0]") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const index_exprt &index_expr= + require_exprt::require_index(out_expr.op0(), 0); + require_exprt::require_symbol(index_expr.array(), "a"); + } + } + WHEN("Constructing from 1+&a[1]") + { + exprt in_expr=to_expr("1+&a[1]", ns); + + CAPTURE(expr2c(in_expr, ns)); + + THEN("The constructed stack should be &a[2]") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const index_exprt &index_expr= + require_exprt::require_index(out_expr.op0(), 2); + require_exprt::require_symbol(index_expr.array(), "a"); + } + } + GIVEN("A symbol int x") + { + typet basic_symbol_type=signedbv_typet(32); + symbolt basic_symbol= + auxiliary_symbolt("x", basic_symbol_type); + symbol_table.add(basic_symbol); + + WHEN("Constructing from &a[x] (x top)") + { + exprt in_expr=to_expr("&a[x]", ns); + + CAPTURE(expr2c(in_expr, ns)); + THEN("The constructed stack should be &a[TOP]") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const index_exprt &index_expr= + require_exprt::require_top_index(out_expr.op0()); + require_exprt::require_symbol(index_expr.array(), "a"); + } + } + WHEN("Constructing from &a[x] (x known to be 2") + { + // Create an abstract_object_pointer representing 2 + abstract_object_pointert x_value= + environment.abstract_object_factory( + basic_symbol_type, + to_expr("2", ns), + ns); + environment.assign(basic_symbol.symbol_expr(), x_value, ns); + + exprt in_expr=to_expr("&a[x]", ns); + + CAPTURE(expr2c(in_expr, ns)); + THEN("The constructed stack should be &a[2]") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const index_exprt &index_expr= + require_exprt::require_index(out_expr.op0(), 2); + require_exprt::require_symbol(index_expr.array(), "a"); + } + } + } + } + + GIVEN("A struct str{ int comp, int comp2 }") + { + struct_union_typet::componentt component("comp", signedbv_typet(32)); + struct_union_typet::componentt component2("comp2", signedbv_typet(32)); + struct_typet struct_type; + struct_type.set_tag("str"); + struct_type.components().push_back(component); + struct_type.components().push_back(component2); + + symbolt struct_symbol; + struct_symbol.base_name="str"; + struct_symbol.name="tag-str"; + struct_symbol.type=struct_type; + struct_symbol.is_type=true; + + symbol_table.add(struct_symbol); + + GIVEN("A struct str s") + { + symbol_table.add( + auxiliary_symbolt("s", struct_type)); + + WHEN("Constructing from &s.comp") + { + exprt in_expr=to_expr("&s.comp", ns); + CAPTURE(expr2c(in_expr, ns)); + + THEN("The constructed stack should be &s.comp") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const member_exprt &member_exrp= + require_exprt::require_member(out_expr.op0(), "comp"); + // TODO: verify member expr + require_exprt::require_symbol(member_exrp.compound(), "s"); + } + } + WHEN("Constructing from &s.comp2") + { + exprt in_expr=to_expr("&s.comp2", ns); + CAPTURE(expr2c(in_expr, ns)); + + THEN("The constructed stack should be &s.comp2") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const member_exprt &member_exrp= + require_exprt::require_member(out_expr.op0(), "comp2"); + // TODO: verify member expr + require_exprt::require_symbol(member_exrp.compound(), "s"); + } + } + WHEN("Constructing from &s") + { + // fiddly as it depends on the type to some degree + // if we want to make a (struct str *) then we want to make a pointer to + // &s + // If it is a pointer to the type of the first component then we really + // want &(s.comp) + // for now we just reject and create a junk stack + exprt in_expr=to_expr("&s", ns); + CAPTURE(expr2c(in_expr, ns)); + + THEN("Then should get a top stack") + { + auto stack=write_stackt(in_expr, environment, ns); + REQUIRE(stack.is_top_value()); + } + } + WHEN("Constructing from &s.comp + 1") + { + // TODO: we could in theory analyse the struct and offset the pointer + // but not yet + exprt in_expr=to_expr("&s.comp + 1", ns); + CAPTURE(expr2c(in_expr, ns)); + + THEN("Then should get a top stack") + { + auto stack=write_stackt(in_expr, environment, ns); + REQUIRE(stack.is_top_value()); + } + } + } + GIVEN("struct str arr_s[5]") + { + typet array_type= + array_typet(struct_type, constant_exprt::integer_constant(5)); + symbol_table.add( + auxiliary_symbolt("arr_s", array_type)); + + WHEN("&arr_s[1].comp") + { + exprt in_expr=to_expr("&arr_s[1].comp", ns); + CAPTURE(expr2c(in_expr, ns)); + + THEN("The constructed stack should be &arr_s[1].comp") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + + const member_exprt &member_expr= + require_exprt::require_member(out_expr.op0(), "comp"); + const index_exprt &index_expr= + require_exprt::require_index(member_expr.compound(), 1); + + require_exprt::require_symbol(index_expr.array(), "arr_s"); + } + } + WHEN("&arr_s[1]") + { + exprt in_expr=to_expr("&arr_s[1]", ns); + CAPTURE(expr2c(in_expr, ns)); + + THEN("The constructed stack should be TOP") + { + // Since we don't allow constructing a pointer to a struct yet + auto stack=write_stackt(in_expr, environment, ns); + REQUIRE(stack.is_top_value()); + } + } + GIVEN("A symbol int x") + { + typet basic_symbol_type=signedbv_typet(32); + symbol_table.add( + auxiliary_symbolt("x", basic_symbol_type)); + + WHEN("Constructing from &arr_s[x].comp (x top)") + { + exprt in_expr=to_expr("&arr_s[x].comp", ns); + + CAPTURE(expr2c(in_expr, ns)); + THEN("The constructed stack should be &arr_s[TOP].comp") + { + auto stack=write_stackt(in_expr, environment, ns); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const member_exprt &member_expr= + require_exprt::require_member(out_expr.op0(), "comp"); + + const index_exprt &index_expr= + require_exprt::require_top_index(member_expr.compound()); + + require_exprt::require_symbol(index_expr.array(), "arr_s"); + } + } + } + } + } + GIVEN("A pointer to an integer int * p = &x") + { + // in a top environment - to construct from say (p + 1) we should always + // return top. If the enviroment was not top, we could do better if p has an + // offset at the top of its write_stack. Of course if it doesn't + + // int x; + typet basic_symbol_type=signedbv_typet(32); + symbol_table.add( + auxiliary_symbolt("x", basic_symbol_type)); + + // int * p + typet pointer_type=pointer_typet(basic_symbol_type); + symbolt pointer_symbol= + auxiliary_symbolt("p", pointer_type); + symbol_table.add(pointer_symbol); + + // Create an abstract_object_pointer representing 2 + abstract_object_pointert x_value= + environment.abstract_object_factory( + pointer_type, + to_expr("&x", ns), + ns); + environment.assign(pointer_symbol.symbol_expr(), x_value, ns); + + WHEN("Constructing the write stack from p + 1") + { + exprt in_expr=to_expr("p + 1", ns); + CAPTURE(expr2c(in_expr, ns)); + + THEN("The constructed stack should be TOP") + { + // Since we don't allow constructing a pointer to a struct yet + auto stack=write_stackt(in_expr, environment, ns); + REQUIRE(stack.is_top_value()); + } + } + WHEN("Constructing the write stack from 1 + p") + { + exprt in_expr=to_expr("1 + p", ns); + CAPTURE(expr2c(in_expr, ns)); + + auto stack=write_stackt(in_expr, environment, ns); + + THEN("Get a top write stack") + { + REQUIRE(stack.is_top_value()); + } + } + WHEN("Constructing the write stack from p - 1") + { + exprt in_expr=to_expr("p - 1", ns); + CAPTURE(expr2c(in_expr, ns)); + + auto stack=write_stackt(in_expr, environment, ns); + + THEN("Get a top write stack") + { + REQUIRE(stack.is_top_value()); + } + } + WHEN("Constructing the write stack from &p[1]") + { + exprt in_expr=to_expr("&p[1]", ns); + CAPTURE(expr2c(in_expr, ns)); + + auto stack=write_stackt(in_expr, environment, ns); + + THEN("Get a top write stack") + { + REQUIRE(stack.is_top_value()); + } + } + } +} +#endif + From 0afbfea26514fd295ad609c43c8673f5b1be3313 Mon Sep 17 00:00:00 2001 From: thk123 Date: Tue, 11 Jul 2017 15:29:49 +0100 Subject: [PATCH 132/342] Use the write_stack in the constant_pointer_abstract_object --- .../pointer_to_array_sensitivity_tests.c | 5 +- .../test.desc | 8 +- .../test.desc | 22 ++-- .../test.desc | 6 +- .../test.desc | 6 +- .../constant_pointer_abstract_object.cpp | 108 ++++++------------ .../constant_pointer_abstract_object.h | 3 +- 7 files changed, 61 insertions(+), 97 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 b379f048a58..e3aebf81673 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 @@ -8,20 +8,21 @@ int main(int argc, char *argv[]) int *p=a; __CPROVER_assert(p==&a[0], "p==&a[0]"); + // Read through pointer __CPROVER_assert(*p==1, "*p==1"); + // Read through offset pointer __CPROVER_assert(p[1]==2, "p[1]==2"); __CPROVER_assert(1[p]==2, "1[p]==2"); __CPROVER_assert(*(p+1)==2, "*(p+1)==2"); __CPROVER_assert(*(1+p)==2, "*(1+p)==2"); - __CPROVER_assert(*(p-1)==1, "*(p-1)==1"); - // Test pointer arithmetic int *q=&a[1]; __CPROVER_assert(q==p+1, "q==p+1"); __CPROVER_assert(*q==2, "*q==2"); + __CPROVER_assert(*(q-1)==1, "*(q-1)==1"); // Test pointer diffs ptrdiff_t x=1; 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 664404a4ab7..63f296b58bf 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 @@ -13,14 +13,14 @@ sensitivity_test_constants_array_of_constants_pointer.c ^\[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.11\] .* \*\(1\+b\)==&b1: SUCCESS$ +^\[main.assertion.12\] .* \*\(1\+b\)==&b3: FAILURE \(if reachable\)$ ^\[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.17\] .* \*\*\(1\+b\)==11: SUCCESS$ +^\[main.assertion.18\] .* \*\*\(1\+b\)==13: FAILURE \(if reachable\)$ ^\[main.assertion.19\] .* \*1\[b\]==11: SUCCESS$ ^\[main.assertion.20\] .* \*1\[b\]==13: FAILURE \(if reachable\)$ ^\[main.assertion.21\] .* c\[0\]==&c0: UNKNOWN$ 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 61fddaeeef5..cc33c98ab65 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,18 @@ sensitivity_test_constants_pointer_to_constants_array.c ^SIGNAL=0$ ^\[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\.3\] .* p\[1\]==2: SUCCESS$ +^\[main\.assertion\.4\] .* 1\[p\]==2: SUCCESS$ +^\[main\.assertion\.5\] .* \*\(p\+1\)==2: SUCCESS$ +^\[main\.assertion\.6\] .* \*\(1\+p\)==2: SUCCESS$ +^\[main\.assertion\.7\] .* q==p\+1: SUCCESS$ +^\[main\.assertion\.8\] .* \*q==2: SUCCESS$ +^\[main\.assertion\.9\] .* \*\(q-1\)==1: SUCCESS$ ^\[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\.11\] .* a\[1\]==4: SUCCESS$ +^\[main\.assertion\.12\] .* a\[1\]==5: SUCCESS$ +^\[main\.assertion\.13\] .* a\[1\]==6: SUCCESS$ +^\[main\.assertion\.14\] .* a\[1\]==7: SUCCESS$ ^\[main\.assertion\.15\] .* \*r==2: UNKNOWN$ ^\[main\.assertion\.16\] .* \*r==1: UNKNOWN$ ^\[main\.assertion\.17\] .* \*s==0: UNKNOWN$ 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 93fafede3ed..c3645e2e7d7 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,9 +9,9 @@ sensitivity_test_constants_pointer_to_two_value_array.c ^\[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\.7\] .* q==p\+1: SUCCESS$ +^\[main.assertion\.8\] .* \*q==2: UNKNOWN$ +^\[main\.assertion\.9\] .* \*\(q-1\)==1: UNKNOWN$ ^\[main.assertion.10\] .* q-p==x: UNKNOWN$ ^\[main.assertion.11\] .* a\[1\]==4: UNKNOWN$ ^\[main.assertion.12\] .* a\[1\]==5: UNKNOWN$ 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 3bbdd3aae25..c2628bc33ab 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,9 +9,9 @@ sensitivity_test_two_value_pointer_to_two_value_array.c ^\[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\.7\] .* q==p\+1: UNKNOWN$ +^\[main\.assertion\.8\] .* \*q==2: UNKNOWN$ +^\[main\.assertion\.9\] .* \*\(q-1\)==1: UNKNOWN$ ^\[main\.assertion\.10\] .* q-p==x: UNKNOWN$ ^\[main\.assertion\.11\] .* a\[1\]==4: UNKNOWN$ ^\[main\.assertion\.12\] .* a\[1\]==5: UNKNOWN$ diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index f4590b9ed94..381c764e46b 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -32,7 +32,6 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( pointer_abstract_objectt(t) { assert(t.id()==ID_pointer); - value=nil_exprt(); } /*******************************************************************\ @@ -56,7 +55,6 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( pointer_abstract_objectt(t, tp, bttm) { assert(t.id()==ID_pointer); - value=nil_exprt(); } /*******************************************************************\ @@ -74,7 +72,7 @@ Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( const constant_pointer_abstract_objectt &old): - pointer_abstract_objectt(old), value(old.value) + pointer_abstract_objectt(old), value_stack(old.value_stack) {} /*******************************************************************\ @@ -94,26 +92,11 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( const exprt &e, const abstract_environmentt &environment, const namespacet &ns): - pointer_abstract_objectt(e, environment, ns) + pointer_abstract_objectt(e, environment, ns), + value_stack(e, environment, ns) { assert(e.type().id()==ID_pointer); - value=nil_exprt(); - - if(e.id()==ID_address_of) - { - value=e; - top=false; - } - else if(e.id()==ID_constant) - { - constant_exprt constant_expr(to_constant_expr(e)); - if(constant_expr.get_value()==ID_NULL) - { - value=e; - top=false; - } - } - // Else unknown expression type - possibly we should handle more + top=value_stack.is_top_value(); } /*******************************************************************\ @@ -174,8 +157,10 @@ abstract_object_pointert } else { - // Can we actually merge these value - if(value==other->value) + bool matching_pointer= + value_stack.to_expression()==other->value_stack.to_expression(); + + if(matching_pointer) { return shared_from_this(); } @@ -213,7 +198,7 @@ exprt constant_pointer_abstract_objectt::to_constant() const { // TODO(tkiley): I think we would like to eval this before using it // in the to_constant. - return value; + return value_stack.to_expression(); } } @@ -236,33 +221,27 @@ Function: constant_pointer_abstract_objectt::output void constant_pointer_abstract_objectt::output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const { - if(is_top() || is_bottom()) + if(is_top() || is_bottom() || value_stack.is_top_value()) { pointer_abstract_objectt::output(out, ai, ns); } else { - if(value.id()==ID_constant && value.get(ID_value)==ID_NULL) - { - out << "NULL"; - } - else + out << "ptr ->("; + const exprt &value=value_stack.to_expression(); + if(value.id()==ID_address_of) { - out << "ptr ->("; - 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 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(); - } - } + const symbol_exprt &symbol_pointed_to( + to_symbol_expr(address_expr.object())); - out << ")"; + out << symbol_pointed_to.get_identifier(); + } } + + out << ")"; } } @@ -286,28 +265,16 @@ 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(is_top() || is_bottom() || value.id()==ID_nil) + if(is_top() || is_bottom() || value_stack.is_top_value()) { // Return top if dereferencing a null pointer or we are top - bool is_value_top = is_top() || value.id()==ID_nil; + bool is_value_top = is_top() || value_stack.is_top_value(); return env.abstract_object_factory( type().subtype(), ns, is_value_top, !is_value_top); } else { - 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(), ns, true, false); - } - else - { - return env.abstract_object_factory(type().subtype(), ns, true, false); - } + return env.eval(value_stack.to_expression().op0(), ns); } } @@ -344,22 +311,13 @@ sharing_ptrt const abstract_object_pointert new_value, bool merging_write) const { - if(is_top() || is_bottom()) + if(is_top() || is_bottom() || value_stack.is_top_value()) { return pointer_abstract_objectt::write_dereference( environment, ns, stack, new_value, merging_write); } 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)); @@ -369,26 +327,30 @@ sharing_ptrt // We should not be changing the type of an abstract object assert(new_value->type()==type().subtype()); - + // Get an expression that we can assign to + exprt value=value_stack.to_expression().op0(); if(merging_write) { abstract_object_pointert pointed_value= - environment.eval(address_expr.object(), ns); + environment.eval(value, ns); bool modifications; abstract_object_pointert merged_value= abstract_objectt::merge(pointed_value, new_value, modifications); - environment.assign(address_expr.object(), merged_value, ns); + environment.assign(value, merged_value, ns); } else { - environment.assign(address_expr.object(), new_value, ns); + environment.assign(value, new_value, ns); } } else { + exprt value=value_stack.to_expression().op0(); abstract_object_pointert pointed_value= - environment.eval(address_expr.object(), ns); - environment.write(pointed_value, new_value, stack, ns, merging_write); + environment.eval(value, ns); + abstract_object_pointert modified_value= + environment.write(pointed_value, new_value, stack, ns, merging_write); + environment.assign(value, modified_value, ns); // but the pointer itself does not change! } diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index afdf1bddffc..d3ccabe9771 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -11,6 +11,7 @@ #include #include +#include class constant_pointer_abstract_objectt:public pointer_abstract_objectt { @@ -57,7 +58,7 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt abstract_object_pointert merge_constant_pointers( const constant_pointer_abstract_pointert other) const; - exprt value; + write_stackt value_stack; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_POINTER_ABSTRACT_OBJECT_H // NOLINT(*) From 2dfa16e23b98ca9fb1d9b191eea89aed64f14d97 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 12 Jul 2017 16:54:03 +0100 Subject: [PATCH 133/342] Modified the write stack to not throw away certain pointers Pointers into arrays was creating a top stack even though the result was valid. Corrected so didn't throw them away (need to look at the base of the stack, not the top). Also made the tests verify that they don't create a top stack when they shouldn't. Also made it impossible to get the expression of a top stack. --- src/analyses/variable-sensitivity/write_stack.cpp | 12 ++++++++---- .../analyses/variable-sensitivity/write_stack.cpp | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/analyses/variable-sensitivity/write_stack.cpp b/src/analyses/variable-sensitivity/write_stack.cpp index 7f9185c631f..bca9b1dde52 100644 --- a/src/analyses/variable-sensitivity/write_stack.cpp +++ b/src/analyses/variable-sensitivity/write_stack.cpp @@ -105,10 +105,12 @@ void write_stackt::construct_stack_to_pointer( if(!top_stack) { - // check the top of the stack is pointing at an array - we don't support - // offset apart from within arrays - std::shared_ptr entry= - *std::prev(stack.cend()); + // check the symbol at the bottom of the stack + std::shared_ptr entry=*stack.cbegin(); + INVARIANT( + entry->get_access_expr().id()==ID_symbol, + "The base should be an addressable location (i.e. symbol)"); + if(entry->get_access_expr().type().id()!=ID_array) { top_stack=true; @@ -175,6 +177,8 @@ void write_stackt::construct_stack_to_array_index( /// for top elements. exprt write_stackt::to_expression() const { + // A top stack is useless and its expression should not be evaluated + PRECONDITION(!is_top_value()); exprt access_expr=nil_exprt(); for(const std::shared_ptr &entry : stack) { diff --git a/unit/analyses/variable-sensitivity/write_stack.cpp b/unit/analyses/variable-sensitivity/write_stack.cpp index 065202a77a1..66389b86976 100644 --- a/unit/analyses/variable-sensitivity/write_stack.cpp +++ b/unit/analyses/variable-sensitivity/write_stack.cpp @@ -66,6 +66,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &x") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -88,6 +89,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &a[0]") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -105,6 +107,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &a") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -122,6 +125,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &a[0]") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -141,6 +145,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &a[1]") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -159,6 +164,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &a[1]") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -178,6 +184,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &a[2]") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -197,6 +204,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &a[0]") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -216,6 +224,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &a[2]") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -241,6 +250,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &a[TOP]") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -267,6 +277,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &a[2]") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -310,6 +321,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &s.comp") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -329,6 +341,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &s.comp2") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -386,6 +399,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &arr_s[1].comp") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); @@ -426,6 +440,7 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be &arr_s[TOP].comp") { auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); const exprt &out_expr=stack.to_expression(); CAPTURE(expr2c(out_expr, ns)); From fb63f24734610e56ee353800f62ae01cf79c7db5 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 13 Jul 2017 09:47:52 +0100 Subject: [PATCH 134/342] Enable the write stack for pointers to structs This works correctly so we don't need to cautiously throw away stacks of pointers to structs. The original concern was pointers to structs being used as pointers to the first component, but the goto program introduces a cast which means we don't create the pointer. Added a unit test to document this behavior. --- .../pointer_to_struct_sensitivity_tests.c | 25 +++++++++++++ .../test.desc | 32 +++++++++++----- .../test.desc | 14 +++++++ .../test.desc | 13 +++++++ .../variable-sensitivity/write_stack.cpp | 8 ---- .../variable-sensitivity/write_stack.cpp | 37 +++++++++++++++---- 6 files changed, 104 insertions(+), 25 deletions(-) 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 52cef2e54e7..1b741048d1a 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 @@ -24,5 +24,30 @@ int main(int argc, char *argv[]) __CPROVER_assert(p->b==2.0, "p->b==2.0"); __CPROVER_assert(p->b==1.0, "p->b==1.0"); + // pointers to components + int * comp_p = &x.a; + __CPROVER_assert(comp_p==&x.a, "comp_p==&x.a"); + __CPROVER_assert(comp_p==&x.b, "comp_p==&x.b"); + __CPROVER_assert(*comp_p==0, "*comp_p==0"); + __CPROVER_assert(*comp_p==1, "*comp_p==1"); + + float * compb_p = &x.b; + __CPROVER_assert(compb_p==&x.a, "compb_p==&x.a"); + __CPROVER_assert(compb_p==&x.b, "compb_p==&x.b"); + __CPROVER_assert(*compb_p==2.0, "*compb_p==2.0"); + __CPROVER_assert(*compb_p==1.0, "*compb_p==1.0"); + + // Use pointer implicitly pointing at the first component + int * implicit_p = &x; + __CPROVER_assert(implicit_p==&x.a, "implicit_p==&x.a"); + __CPROVER_assert(implicit_p==&x, "implicit_p==&x"); + __CPROVER_assert(*implicit_p==0, "*implicit_p==0"); + __CPROVER_assert(*implicit_p==1, "*implicit_p==1"); + + // Write through pointer implicitly pointing at the first component + *implicit_p=5; + __CPROVER_assert(x.a==5, "x.a==5"); + __CPROVER_assert(x.a==1, "x.a==1"); + return 0; } 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 de0638dc86b..2f5839853c5 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 @@ -1,16 +1,30 @@ -FUTURE +CORE sensitivity_test_constants_pointer_to_constants_struct.c --variable --pointers --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[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\)$ +^\[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\)$ +^\[main\.assertion\.9\] .* \*comp_p==0: SUCCESS$ +^\[main\.assertion\.10\] .* \*comp_p==1: FAILURE \(if reachable\)$ +^\[main\.assertion\.13\] .* \*compb_p==2.0: SUCCESS$ +^\[main\.assertion\.14\] .* \*compb_p==1.0: FAILURE \(if reachable\)$ +^\[main\.assertion\.17\] .* \*implicit_p==0: UNKNOWN$ +^\[main\.assertion\.18\] .* \*implicit_p==1: UNKNOWN$ +^\[main\.assertion\.19\] .* x.a==5: UNKNOWN$ +^\[main\.assertion\.20\] .* x.a==1: UNKNOWN$ -- ^warning: ignoring -- -The final two assertions are the wrong way round as modifying the pointer -does not seem to be propogating through. See #96 +The following assertions are not checked since simplify_expr doesn't handle +them. See issue diffblue/cbmc-toyota#145 +^\[main\.assertion\.7\] .* comp_p==&x.a: SUCCESS +^\[main\.assertion\.8\] .* comp_p==&x.b: FAILURE \(if reachable\)$ +^\[main\.assertion\.11\] .* compb_p==&x.a: FAILURE \(if reachable\)$ +^\[main\.assertion\.12\] .* compb_p==&x.b: SUCCESS +^\[main\.assertion\.15\] .* implicit_p==&x.a: SUCCESS +^\[main\.assertion\.16\] .* implicit_p==&x: SUCCESS 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 4c425b0ac6e..359264c686d 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 @@ -9,5 +9,19 @@ sensitivity_test_constants_pointer_to_two_value_struct.c ^\[main.assertion.4\] .* p->a==1: UNKNOWN$ ^\[main.assertion.5\] .* p->b==2.0: UNKNOWN$ ^\[main.assertion.6\] .* p->b==1.0: UNKNOWN$ +\[main\.assertion\.7\] .* comp_p==&x\.a: UNKNOWN$ +\[main\.assertion\.8\] .* comp_p==&x\.b: UNKNOWN$ +\[main\.assertion\.9\] .* \*comp_p==0: UNKNOWN$ +\[main\.assertion\.10\] .* \*comp_p==1: UNKNOWN$ +\[main\.assertion\.11\] .* compb_p==&x\.a: UNKNOWN$ +\[main\.assertion\.12\] .* compb_p==&x\.b: UNKNOWN$ +\[main\.assertion\.13\] .* \*compb_p==2\.0: UNKNOWN$ +\[main\.assertion\.14\] .* \*compb_p==1\.0: UNKNOWN$ +\[main\.assertion\.15\] .* implicit_p==&x\.a: UNKNOWN$ +\[main\.assertion\.16\] .* implicit_p==&x: UNKNOWN$ +\[main\.assertion\.17\] .* \*implicit_p==0: UNKNOWN$ +\[main\.assertion\.18\] .* \*implicit_p==1: UNKNOWN$ +\[main\.assertion\.19\] .* x\.a==5: UNKNOWN$ +\[main\.assertion\.20\] .* x\.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 67c09b58e1f..65edb0a87ed 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 @@ -9,5 +9,18 @@ sensitivity_test_two_value_pointer_to_two_value_struct.c ^\[main.assertion.4\] .* p->a==1: UNKNOWN$ ^\[main.assertion.5\] .* p->b==2.0: UNKNOWN$ ^\[main.assertion.6\] .* p->b==1.0: UNKNOWN$ +^\[main.assertion.8\] .* comp_p==&x.b: UNKNOWN$ +^\[main.assertion.9\] .* \*comp_p==0: UNKNOWN$ +^\[main.assertion.10\] .* \*comp_p==1: UNKNOWN$ +^\[main.assertion.11\] .* compb_p==&x.a: UNKNOWN$ +^\[main.assertion.12\] .* compb_p==&x.b: UNKNOWN$ +^\[main.assertion.13\] .* \*compb_p==2.0: UNKNOWN$ +^\[main.assertion.14\] .* \*compb_p==1.0: UNKNOWN$ +^\[main.assertion.15\] .* implicit_p==&x.a: UNKNOWN$ +^\[main.assertion.16\] .* implicit_p==&x: UNKNOWN$ +^\[main.assertion.17\] .* \*implicit_p==0: UNKNOWN$ +^\[main.assertion.18\] .* \*implicit_p==1: UNKNOWN$ +^\[main.assertion.19\] .* x.a==5: UNKNOWN$ +^\[main.assertion.20\] .* x.a==1: UNKNOWN$ -- ^warning: ignoring diff --git a/src/analyses/variable-sensitivity/write_stack.cpp b/src/analyses/variable-sensitivity/write_stack.cpp index bca9b1dde52..30ec0e07dc8 100644 --- a/src/analyses/variable-sensitivity/write_stack.cpp +++ b/src/analyses/variable-sensitivity/write_stack.cpp @@ -60,14 +60,6 @@ void write_stackt::construct_stack_to_pointer( { PRECONDITION(expr.type().id()==ID_pointer); - // If we are a pointer to a struct, we do not currently support reading - // writing directly to it so just create a top stack - if(ns.follow(expr.type().subtype()).id()==ID_struct) - { - top_stack=true; - return; - } - if(expr.id()==ID_address_of) { // resovle reminder, can either be a symbol, member or index of diff --git a/unit/analyses/variable-sensitivity/write_stack.cpp b/unit/analyses/variable-sensitivity/write_stack.cpp index 66389b86976..0ec3c9cd30b 100644 --- a/unit/analyses/variable-sensitivity/write_stack.cpp +++ b/unit/analyses/variable-sensitivity/write_stack.cpp @@ -355,15 +355,29 @@ SCENARIO("Constructing write stacks", } WHEN("Constructing from &s") { - // fiddly as it depends on the type to some degree - // if we want to make a (struct str *) then we want to make a pointer to - // &s - // If it is a pointer to the type of the first component then we really - // want &(s.comp) - // for now we just reject and create a junk stack exprt in_expr=to_expr("&s", ns); CAPTURE(expr2c(in_expr, ns)); + THEN("Then should get a write stack representing &s") + { + auto stack=write_stackt(in_expr, environment, ns); + REQUIRE_FALSE(stack.is_top_value()); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const exprt &object=out_expr.op0(); + require_exprt::require_symbol(object, "s"); + } + } + WHEN("Constructing from (int *)&s") + { + // TODO: we could in theory analyse the struct and offset the pointer + // but not yet + exprt in_expr=to_expr("(int *)&s", ns); + CAPTURE(expr2c(in_expr, ns)); + THEN("Then should get a top stack") { auto stack=write_stackt(in_expr, environment, ns); @@ -421,9 +435,16 @@ SCENARIO("Constructing write stacks", THEN("The constructed stack should be TOP") { - // Since we don't allow constructing a pointer to a struct yet auto stack=write_stackt(in_expr, environment, ns); - REQUIRE(stack.is_top_value()); + REQUIRE_FALSE(stack.is_top_value()); + const exprt &out_expr=stack.to_expression(); + + CAPTURE(expr2c(out_expr, ns)); + + REQUIRE(out_expr.id()==ID_address_of); + const exprt &object=out_expr.op0(); + const index_exprt &index_expr=require_exprt::require_index(object, 1); + require_exprt::require_symbol(index_expr.array(), "arr_s"); } } GIVEN("A symbol int x") From 1da03e080585782334c2ad4d7e168e639a2ee187 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 13 Jul 2017 10:26:24 +0100 Subject: [PATCH 135/342] Enabling some of these assertions in tests related to arrays We have to turn on pointer sensitivity or otherwise when evaluating these expressions we won't get the correct write stack. --- .../test.desc | 10 +++++----- .../sensitivity-test-constants-array/test.desc | 6 +++--- 2 files changed, 8 insertions(+), 8 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 d6beba0c05f..34a40e94989 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,6 +1,6 @@ CORE sensitivity_test_constants_array_of_constants_array.c ---variable --arrays --verify +--variable --arrays --verify --pointers ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* a\[1\]\[2\]==0: SUCCESS$ @@ -17,10 +17,10 @@ sensitivity_test_constants_array_of_constants_array.c ^\[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.15\] .* \(\*\(1\+b\)\)\[2\]==5: SUCCESS$ +^\[main.assertion.16\] .* \(\*\(1\+b\)\)\[2\]==0: FAILURE \(if reachable\)$ +^\[main.assertion.17\] .* \*\(\*\(1\+b\)\+2\)==5: SUCCESS$ +^\[main.assertion.18\] .* \*\(\*\(1\+b\)\+2\)==0: FAILURE \(if reachable\)$ ^\[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$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array/test.desc index 79137cd1c26..f3159eda917 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_test_constants_array.c ---variable --arrays --verify +--variable --arrays --verify --pointers ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* a\[1\]==0: SUCCESS$ @@ -9,8 +9,8 @@ sensitivity_test_constants_array.c ^\[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.7\] .* \*\(1\+b\)==0: SUCCESS$ +^\[main.assertion.8\] .* \*\(1\+b\)==1: FAILURE \(if reachable\)$ ^\[main.assertion.9\] .* 1\[b\]==0: SUCCESS$ ^\[main.assertion.10\] .* 1\[b\]==1: FAILURE \(if reachable\)$ ^\[main.assertion.11\] .* c\[0\]==0: SUCCESS$ From 6831a943cf8ea2e64ef4eba9aa63829874f9c94c Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 25 Oct 2017 09:26:56 +0100 Subject: [PATCH 136/342] Correctly identify bitfield constants as CONSTANT values Previously constant bitfield values were identified as TWO_VALUE by default, meaning they became TOP immediately. This change makes them be correctly identified as constants and hence have their values tracked appropriately. --- .../main.c | 14 ++++++++++++++ .../test.desc | 8 ++++++++ .../variable_sensitivity_object_factory.cpp | 3 ++- 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 regression/goto-analyzer/variable-sensitivity-bit-field-constants/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-bit-field-constants/main.c b/regression/goto-analyzer/variable-sensitivity-bit-field-constants/main.c new file mode 100644 index 00000000000..013100b8895 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-bit-field-constants/main.c @@ -0,0 +1,14 @@ +struct bitfield_struct { + unsigned char byte; + unsigned char bitfield:1; +}; + +extern struct bitfield_struct bs; + +void main(void) +{ + bs.byte = 10; + bs.bitfield = 1; + __CPROVER_assert(bs.byte==10, "bs.byte==10"); + __CPROVER_assert(bs.bitfield==1, "bs.bitfield==1"); +} diff --git a/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc b/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc new file mode 100644 index 00000000000..f7c393c437b --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--function main --variable --structs --verify +^EXIT=0$ +^SIGNAL=0$ +\[main\.assertion\.1\] .* bs\.byte==10: Success +\[main\.assertion\.2\] .* bs\.bitfield==1: Success +-- diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 39e6eca3c48..3c90b492506 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -32,7 +32,8 @@ 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_integer) + type.id()==ID_c_bool || type.id()==ID_bool || + type.id()==ID_integer || type.id()==ID_c_bit_field) { abstract_object_type=CONSTANT; } From 0ebc7ec6bef3d48b817543e3d4ba028ec5251711 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 25 Oct 2017 10:39:40 +0100 Subject: [PATCH 137/342] Driveby cleanup to keep Lint happy --- .../variable_sensitivity_object_factory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 3c90b492506..bde525f855c 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -127,7 +127,7 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: return initialize_abstract_object( followed_type, top, bottom, e, environment, ns); default: - assert(false); + UNREACHABLE; return initialize_abstract_object( followed_type, top, bottom, e, environment, ns); } From cb82f55f89c7e3753fc4e5a3ec4f114cbb0f9787 Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Thu, 27 Jul 2017 17:04:48 +0100 Subject: [PATCH 138/342] Add initial output functions for all sub-classes except pointer. --- .../abstract_enviroment.cpp | 19 +++++++++++++++++++ .../variable-sensitivity/abstract_object.h | 8 ++++++++ .../constant_array_abstract_object.cpp | 19 +++++++++++++++++++ .../full_struct_abstract_object.cpp | 19 +++++++++++++++++++ 4 files changed, 65 insertions(+) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index c7974d588a8..3c727af23bb 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -710,6 +710,25 @@ void abstract_environmentt::output( out << entry.first.get_identifier() << " (" << ") -> "; entry.second->output(out, ai, ns); + + // Start outputting specific last_written_locations + out << " @ ["; + bool comma=false; + for (auto location: entry.second->get_last_written_locations()) + { + if(!comma) + { + out << location->location_number; + comma=true; + } + else + { + out << ", " << location->location_number; + } + } + out << "]"; + // Finish outputting last_written_locations + out << "\n"; } out << "}\n"; diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 4eaf850d472..0262f5b3226 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -30,9 +30,11 @@ #include #include #include +#include #include + class typet; class constant_exprt; class abstract_environmentt; @@ -108,10 +110,16 @@ class abstract_objectt:public std::enable_shared_from_this abstract_object_pointert op2, bool &out_modifications); + std::vector get_last_written_locations() const + { + return last_written_locations; + } + private: // To enforce copy-on-write these are private and have read-only accessors typet t; bool bottom; + std::vector last_written_locations; abstract_object_pointert abstract_object_merge( const abstract_object_pointert other) const; diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index c9b427e3eb1..e6309b17ce3 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -193,6 +193,25 @@ void constant_array_abstract_objectt::output( { out << "[" << entry.first << "] = "; entry.second->output(out, ai, ns); + + // Start outputting specific last_written_locations + out << " @ ["; + bool comma=false; + for(auto location: entry.second->get_last_written_locations()) + { + if(!comma) + { + out << location->location_number; + comma=true; + } + else + { + out << ", " << location->location_number; + } + } + out << "]"; + // End outputting specific last_written_locations + out << "\n"; } out << "}"; diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 466816e468f..0ff00d82fac 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -285,6 +285,25 @@ void full_struct_abstract_objectt::output( } out << "." << entry.first << "="; entry.second->output(out, ai, ns); + + // Start outputting specific last_written_locations + out << " @ ["; + bool comma=false; + for(auto loc: entry.second->get_last_written_locations()) + { + if(!comma) + { + out << loc->location_number; + comma=true; + } + else + { + out << ", " << loc->location_number; + } + } + out << "]"; + // End outputting specific last_written_locations + } out << "}"; } From be961e772592859132d5b3ca95ceebd860133304 Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Thu, 27 Jul 2017 17:44:38 +0100 Subject: [PATCH 139/342] Add method to update last_written_locations and used it provisionally in ASSIGN. --- src/analyses/variable-sensitivity/abstract_object.h | 8 ++++++++ .../variable-sensitivity/variable_sensitivity_domain.cpp | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 0262f5b3226..dcc4d00a307 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -110,6 +110,14 @@ class abstract_objectt:public std::enable_shared_from_this abstract_object_pointert op2, bool &out_modifications); + abstract_object_pointert update_last_written_locations(goto_programt::const_targett &location) const + { + internal_abstract_object_pointert clone = mutable_clone(); + clone->last_written_locations.clear(); + clone->last_written_locations.push_back(location); + return clone; + } + std::vector get_last_written_locations() const { return last_written_locations; diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 0a3707cc20e..bf404e7bb43 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -72,7 +72,8 @@ 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, ns); + abstract_object_pointert rhs = r->update_last_written_locations(from); + abstract_state.assign(inst.lhs(), rhs, ns); } break; From 5ff41acec1fef64005df588fd3dc65e4c157aae4 Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Thu, 27 Jul 2017 20:01:04 +0100 Subject: [PATCH 140/342] Experimental helper functions and an attempt to note destroy information for derefs, but do destroy (and correct!) information for other LHS assigns. --- src/analyses/variable-sensitivity/NOTES.md | 24 ++++++++++++++ .../abstract_enviroment.cpp | 16 ++++++++- .../variable-sensitivity/abstract_object.h | 33 +++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 src/analyses/variable-sensitivity/NOTES.md diff --git a/src/analyses/variable-sensitivity/NOTES.md b/src/analyses/variable-sensitivity/NOTES.md new file mode 100644 index 00000000000..ff7e36497a5 --- /dev/null +++ b/src/analyses/variable-sensitivity/NOTES.md @@ -0,0 +1,24 @@ +Issues + + int x[4] = {1, 2, 3, 4}; +-> + main::1::x () -> {[0] = 00000000000000000000000000000001 @ [] + [1] = 00000000000000000000000000000010 @ [] + [2] = 00000000000000000000000000000011 @ [] + [3] = 00000000000000000000000000000100 @ [] + } @ [1] + +Problem is that on generation of each element there needs to be a copy +of the instruction location, but this would be a substantial change to the codebase. + +Could be handled as a special case. + +-- + +m.age = 10; + +main::1::m () -> {.age=00000000000000000000000000001010 @ [2]} @ [] + +Should be? + +main::1::m () -> {.age=00000000000000000000000000001010 @ [2]} @ [2] \ No newline at end of file diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 3c727af23bb..c04f506e618 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -185,6 +185,8 @@ bool abstract_environmentt::assign( return !bottom_at_start; } + bool contains_dereference=false; + abstract_object_pointert lhs_value=nullptr; // Build a stack of index, member and dereference accesses which // we will work through the relevant abstract objects @@ -192,6 +194,10 @@ bool abstract_environmentt::assign( std::stack stactions; // I'm not a continuation, honest guv' while(s.id() != ID_symbol) { + if(s.id() == ID_dereference) + { + contains_dereference=true; + } if(s.id() == ID_index || s.id() == ID_member || s.id() == ID_dereference) { stactions.push(s); @@ -219,6 +225,13 @@ bool abstract_environmentt::assign( } } + if(!contains_dereference) + { + lhs_value=lhs_value->update_last_written_locations(value); + } + // This ensures the entire symbol updates at each write + // (As requested by Thomas.) + abstract_object_pointert final_value; // This is the root abstract object that is in the map of abstract objects @@ -254,7 +267,8 @@ bool abstract_environmentt::assign( symbol_exprt symbol_expr=to_symbol_expr(s); if(final_value->is_top()) { - map.erase(symbol_expr); + // We mustn't erase TOP now. Lose information. +// map.erase(symbol_expr); } else { diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index dcc4d00a307..edf08058603 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -118,6 +118,39 @@ class abstract_objectt:public std::enable_shared_from_this return clone; } + abstract_object_pointert update_last_written_locations(const abstract_object_pointert &object) const + { + internal_abstract_object_pointert clone = mutable_clone(); + clone->last_written_locations.clear(); + for(auto location: object->get_last_written_locations()) + { + clone->last_written_locations.push_back(location); + } + return clone; + } + + void set_last_written_locations(const abstract_object_pointert &object) + { + std::cout << "* Setting last written locations\n"; + last_written_locations.clear(); + for(auto location: object->get_last_written_locations()) + { + last_written_locations.push_back(location); + } + } + + bool contains_last_written_location(goto_programt::const_targett &find) + { + for(auto location: last_written_locations) + { + if(location->location_number == find->location_number) + { + return true; + } + } + return false; + } + std::vector get_last_written_locations() const { return last_written_locations; From 0ae3135f64efb6f9320fa13a264e081b488ca728 Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Fri, 28 Jul 2017 09:50:27 +0100 Subject: [PATCH 141/342] Initial merge implementation, some new helper functions (to be moved to cpp and pruned), some notes and disabled removal of TOP elements. --- src/analyses/variable-sensitivity/NOTES.md | 4 +- .../abstract_enviroment.cpp | 10 +++-- .../variable-sensitivity/abstract_object.cpp | 7 ++++ .../variable-sensitivity/abstract_object.h | 41 ++++++++++++++++++- 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/src/analyses/variable-sensitivity/NOTES.md b/src/analyses/variable-sensitivity/NOTES.md index ff7e36497a5..babbaf01c2a 100644 --- a/src/analyses/variable-sensitivity/NOTES.md +++ b/src/analyses/variable-sensitivity/NOTES.md @@ -21,4 +21,6 @@ main::1::m () -> {.age=00000000000000000000000000001010 @ [2]} @ [] Should be? -main::1::m () -> {.age=00000000000000000000000000001010 @ [2]} @ [2] \ No newline at end of file +main::1::m () -> {.age=00000000000000000000000000001010 @ [2]} @ [2] + +tl;dr: Copying objects with subelements. \ No newline at end of file diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index c04f506e618..b9f2a25bea6 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -568,8 +568,9 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) if(map[entry.first]->is_top()) { - map.erase(entry.first); - modified=true; + // Don't remove TOP items. + //map.erase(entry.first); + //modified=true; #ifdef DEBUG std::cout << "Removing " << entry.first.get_identifier() << std::endl; #endif @@ -590,8 +591,9 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) { // 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; + // Don't erase + //map.erase(iter++); + //modified=true; #ifdef DEBUG std::cout << "Removing " << iter->first.get_identifier() << std::endl; diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 15b21f6c27a..60ed305d94d 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -309,6 +309,13 @@ abstract_object_pointert abstract_objectt::merge( op1->abstract_object_merge(op2):op1->merge(op2); // If no modifications, we will return the original pointer out_modifications=result!=op1; + + std::vector get_merged_locations = op1->get_new_location_set(op2); + if(get_merged_locations.size() > op1->get_last_written_locations().size()) + { + result=result->update_last_written_locations(get_merged_locations); + } + return result; } diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index edf08058603..90e44750c19 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -129,9 +129,48 @@ class abstract_objectt:public std::enable_shared_from_this return clone; } + abstract_object_pointert update_last_written_locations(std::vector &locations) const + { + internal_abstract_object_pointert clone = mutable_clone(); + clone->last_written_locations.clear(); + for(auto location: locations) + { + clone->last_written_locations.push_back(location); + } + return clone; + } + + // Cheap and dirty diff calculation. + // Moving to (unordered)_sets would allow reliance on built ins. + std::vector get_new_location_set(const abstract_object_pointert &other) const + { + std::vector locations = this->get_last_written_locations(); + std::vector more_locations = other->get_last_written_locations(); + + for(auto add_location:more_locations) + { + bool found=false; + for(auto location:locations) + { + if(location->location_number == add_location->location_number) + { + found=true; + break; + } + } + if(found==false) + { + locations.push_back(add_location); + } + } + + return locations; + } + + + // For mutable void set_last_written_locations(const abstract_object_pointert &object) { - std::cout << "* Setting last written locations\n"; last_written_locations.clear(); for(auto location: object->get_last_written_locations()) { From a5aad7ee7ab15859383d0db194cee0c8652ba1de Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Fri, 28 Jul 2017 10:58:22 +0100 Subject: [PATCH 142/342] Add erase methods and pointer handling. --- .../abstract_enviroment.cpp | 33 +++++++------------ .../abstract_enviroment.h | 3 +- .../constant_pointer_abstract_object.cpp | 6 +--- .../variable_sensitivity_domain.cpp | 11 ++++++- 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index b9f2a25bea6..154645067b5 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -174,7 +174,8 @@ Function: abstract_environmentt::assign \*******************************************************************/ bool abstract_environmentt::assign( - const exprt &expr, const abstract_object_pointert value, const namespacet &ns) + const exprt &expr, const abstract_object_pointert value, const namespacet &ns, + bool erase) { assert(value); @@ -185,8 +186,6 @@ bool abstract_environmentt::assign( return !bottom_at_start; } - bool contains_dereference=false; - abstract_object_pointert lhs_value=nullptr; // Build a stack of index, member and dereference accesses which // we will work through the relevant abstract objects @@ -194,10 +193,6 @@ bool abstract_environmentt::assign( std::stack stactions; // I'm not a continuation, honest guv' while(s.id() != ID_symbol) { - if(s.id() == ID_dereference) - { - contains_dereference=true; - } if(s.id() == ID_index || s.id() == ID_member || s.id() == ID_dereference) { stactions.push(s); @@ -225,19 +220,10 @@ bool abstract_environmentt::assign( } } - if(!contains_dereference) - { - lhs_value=lhs_value->update_last_written_locations(value); - } - // This ensures the entire symbol updates at each write - // (As requested by Thomas.) - 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 @@ -265,17 +251,20 @@ bool abstract_environmentt::assign( if(s.id()==ID_symbol) { symbol_exprt symbol_expr=to_symbol_expr(s); - if(final_value->is_top()) + + if(erase) { - // We mustn't erase TOP now. Lose information. -// map.erase(symbol_expr); + map.erase(symbol_expr); + return true; } - else + + if(final_value != map[symbol_expr]) { - map[symbol_expr]=final_value; + map[symbol_expr]=final_value->update_last_written_locations(value); + return true; } } - return true; + return false; } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index bd6e9c0fdb0..51a8566bb70 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -27,7 +27,8 @@ class abstract_environmentt virtual bool assign( const exprt &expr, const abstract_object_pointert value, - const namespacet &ns); + const namespacet &ns, + bool erase=false); virtual bool assume(const exprt &expr, const namespacet &ns); virtual abstract_object_pointert write( diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 381c764e46b..764638fd2db 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -318,10 +318,6 @@ sharing_ptrt } else { - sharing_ptrt copy= - sharing_ptrt( - new constant_pointer_abstract_objectt(*this)); - if(stack.empty()) { // We should not be changing the type of an abstract object @@ -354,6 +350,6 @@ sharing_ptrt // but the pointer itself does not change! } - return copy; + return std::dynamic_pointer_cast(shared_from_this()); } } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index bf404e7bb43..3426198d03a 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -51,6 +51,15 @@ void variable_sensitivity_domaint::transform( switch(instruction.type) { case DECL: + { + abstract_object_pointert top_object= + abstract_state.abstract_object_factory( + to_code_decl(instruction.code).symbol().type(), ns, true)-> + update_last_written_locations(from); + abstract_state.assign( + to_code_decl(instruction.code).symbol(), top_object, ns); + } + // Creates a new variable, which should be top // but we don't store top so ... no action required break; @@ -62,7 +71,7 @@ void variable_sensitivity_domaint::transform( abstract_state.abstract_object_factory( to_code_dead(instruction.code).symbol().type(), ns, true); abstract_state.assign( - to_code_dead(instruction.code).symbol(), top_object, ns); + to_code_dead(instruction.code).symbol(), top_object, ns, true); } break; From 316b9ae48042df4a00f02c031dba48e0bc74832e Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Fri, 28 Jul 2017 11:54:46 +0100 Subject: [PATCH 143/342] Brief auxiliary function tidy-up --- .../abstract_enviroment.cpp | 3 +- .../variable-sensitivity/abstract_object.h | 41 +++++-------------- .../variable_sensitivity_domain.cpp | 8 ++-- 3 files changed, 17 insertions(+), 35 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 154645067b5..cdb5f61e7fe 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -260,7 +260,8 @@ bool abstract_environmentt::assign( if(final_value != map[symbol_expr]) { - map[symbol_expr]=final_value->update_last_written_locations(value); + map[symbol_expr]=final_value + ->update_last_written_locations(value->get_last_written_locations()); return true; } } diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 90e44750c19..d9fb2264378 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -110,33 +110,19 @@ class abstract_objectt:public std::enable_shared_from_this abstract_object_pointert op2, bool &out_modifications); - abstract_object_pointert update_last_written_locations(goto_programt::const_targett &location) const + abstract_object_pointert update_last_written_locations(const goto_programt::const_targett &location) const { - internal_abstract_object_pointert clone = mutable_clone(); + internal_abstract_object_pointert clone=mutable_clone(); clone->last_written_locations.clear(); clone->last_written_locations.push_back(location); return clone; } - abstract_object_pointert update_last_written_locations(const abstract_object_pointert &object) const + abstract_object_pointert update_last_written_locations(const std::vector &locations) const { - internal_abstract_object_pointert clone = mutable_clone(); + internal_abstract_object_pointert clone=mutable_clone(); clone->last_written_locations.clear(); - for(auto location: object->get_last_written_locations()) - { - clone->last_written_locations.push_back(location); - } - return clone; - } - - abstract_object_pointert update_last_written_locations(std::vector &locations) const - { - internal_abstract_object_pointert clone = mutable_clone(); - clone->last_written_locations.clear(); - for(auto location: locations) - { - clone->last_written_locations.push_back(location); - } + clone->last_written_locations=locations; return clone; } @@ -144,8 +130,8 @@ class abstract_objectt:public std::enable_shared_from_this // Moving to (unordered)_sets would allow reliance on built ins. std::vector get_new_location_set(const abstract_object_pointert &other) const { - std::vector locations = this->get_last_written_locations(); - std::vector more_locations = other->get_last_written_locations(); + std::vector locations=this->get_last_written_locations(); + std::vector more_locations=other->get_last_written_locations(); for(auto add_location:more_locations) { @@ -178,16 +164,11 @@ class abstract_objectt:public std::enable_shared_from_this } } - bool contains_last_written_location(goto_programt::const_targett &find) + // For mutable + void set_last_written_locations(goto_programt::const_targett &location) { - for(auto location: last_written_locations) - { - if(location->location_number == find->location_number) - { - return true; - } - } - return false; + last_written_locations.clear(); + last_written_locations.push_back(location); } std::vector get_last_written_locations() const diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 3426198d03a..6420e803fa0 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -54,8 +54,8 @@ void variable_sensitivity_domaint::transform( { abstract_object_pointert top_object= abstract_state.abstract_object_factory( - to_code_decl(instruction.code).symbol().type(), ns, true)-> - update_last_written_locations(from); + to_code_decl(instruction.code).symbol().type(), ns, true) + ->update_last_written_locations(from); abstract_state.assign( to_code_decl(instruction.code).symbol(), top_object, ns); } @@ -80,8 +80,8 @@ 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(), ns); - abstract_object_pointert rhs = r->update_last_written_locations(from); + abstract_object_pointert rhs = abstract_state.eval(inst.rhs(), ns) + ->update_last_written_locations(from); abstract_state.assign(inst.lhs(), rhs, ns); } break; From 3616a1e87030fd0d1f5c0f648c45180268d7e4a2 Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Fri, 28 Jul 2017 12:21:42 +0100 Subject: [PATCH 144/342] Finished prior to clean. --- .../variable-sensitivity/abstract_enviroment.cpp | 9 +-------- src/analyses/variable-sensitivity/abstract_enviroment.h | 3 +-- src/analyses/variable-sensitivity/abstract_object.h | 8 ++++++++ .../constant_array_abstract_object.h | 8 ++++++++ .../variable-sensitivity/full_struct_abstract_object.h | 7 +++++++ .../variable-sensitivity/variable_sensitivity_domain.cpp | 9 +++++++-- 6 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index cdb5f61e7fe..e633ec6fb87 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -174,8 +174,7 @@ Function: abstract_environmentt::assign \*******************************************************************/ bool abstract_environmentt::assign( - const exprt &expr, const abstract_object_pointert value, const namespacet &ns, - bool erase) + const exprt &expr, const abstract_object_pointert value, const namespacet &ns) { assert(value); @@ -252,12 +251,6 @@ bool abstract_environmentt::assign( { symbol_exprt symbol_expr=to_symbol_expr(s); - if(erase) - { - map.erase(symbol_expr); - return true; - } - if(final_value != map[symbol_expr]) { map[symbol_expr]=final_value diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 51a8566bb70..bd6e9c0fdb0 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -27,8 +27,7 @@ class abstract_environmentt virtual bool assign( const exprt &expr, const abstract_object_pointert value, - const namespacet &ns, - bool erase=false); + const namespacet &ns); virtual bool assume(const exprt &expr, const namespacet &ns); virtual abstract_object_pointert write( diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index d9fb2264378..86a2e327377 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -110,11 +110,19 @@ class abstract_objectt:public std::enable_shared_from_this abstract_object_pointert op2, bool &out_modifications); + + virtual void update_sub_elements(const goto_programt::const_targett &location) + { + return; + } + + abstract_object_pointert update_last_written_locations(const goto_programt::const_targett &location) const { internal_abstract_object_pointert clone=mutable_clone(); clone->last_written_locations.clear(); clone->last_written_locations.push_back(location); + clone->update_sub_elements(location); return clone; } diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index 24a8c87799e..7c7fb5be354 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -72,6 +72,14 @@ class constant_array_abstract_objectt:public array_abstract_objectt abstract_object_pointert constant_array_merge( const constant_array_pointert other) const; + + virtual void update_sub_elements(const goto_programt::const_targett &location) override + { + for(auto &item: map) + { + item.second=item.second->update_last_written_locations(location); + } + } }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ARRAY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 2c8794903ca..7261e8b2b65 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -57,6 +57,13 @@ class full_struct_abstract_objectt:public struct_abstract_objectt struct_mapt map; + virtual void update_sub_elements(const goto_programt::const_targett &location) override + { + for(auto &item: map) + { + item.second=item.second->update_last_written_locations(location); + } + } abstract_object_pointert merge_constant_structs( constant_struct_pointert other) const; diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 6420e803fa0..1d3fb763366 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -67,11 +67,16 @@ void variable_sensitivity_domaint::transform( case DEAD: { // Assign to top is the same as removing + // TO DO: Erase +// map.erase(to_code_dead(instruction.code).symbol()); +// return true; + + abstract_object_pointert top_object= abstract_state.abstract_object_factory( to_code_dead(instruction.code).symbol().type(), ns, true); - abstract_state.assign( - to_code_dead(instruction.code).symbol(), top_object, ns, true); +// abstract_state.assign( +// to_code_dead(instruction.code).symbol(), top_object, ns, true); } break; From c6ae03ebb2a0d2c7121cd441c087bdd7679dd488 Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Fri, 28 Jul 2017 14:19:12 +0100 Subject: [PATCH 145/342] Implemented "last written location" tracking abstract objects Each abstract_objectt now has an std::set ("last write locations") data structure attached to it. For each assign instruction, whenever an object is assigned to a value, the last write location set for that object is cleared, and updated to contain the program location (specifically the const_targett.) Furthermore, if the object is not a simple symbol (e.g. struct, array), then the high-level symbol is also updated to represent modification. (unless it's a pointer write, in which case only modified objects are updated.) For writes where multiple objects are copied 'simultaneously' (within a single GOTO instruction, for example int a[2] = { 3, 4 } then all sub-elements of the written object are also updated. So in this case, given current location is X, then last_written_locations will appoximately map a->X, a[0]->X, a[1]->X. This applies recursively. Merges perform an additional union between objects' last write location sets. The last_written_locations information is automatically outputted if output() is called, it is represented by a @ [X] or a @[X, Y], etc. --- src/analyses/variable-sensitivity/NOTES.md | 26 ----- .../abstract_enviroment.cpp | 57 +++++------ .../abstract_enviroment.h | 2 + .../variable-sensitivity/abstract_object.cpp | 96 ++++++++++++++++++- .../variable-sensitivity/abstract_object.h | 91 +++--------------- .../constant_array_abstract_object.cpp | 26 ++++- .../constant_array_abstract_object.h | 8 +- .../full_struct_abstract_object.cpp | 25 +++++ .../full_struct_abstract_object.h | 9 +- .../variable_sensitivity_domain.cpp | 25 ++--- 10 files changed, 195 insertions(+), 170 deletions(-) delete mode 100644 src/analyses/variable-sensitivity/NOTES.md diff --git a/src/analyses/variable-sensitivity/NOTES.md b/src/analyses/variable-sensitivity/NOTES.md deleted file mode 100644 index babbaf01c2a..00000000000 --- a/src/analyses/variable-sensitivity/NOTES.md +++ /dev/null @@ -1,26 +0,0 @@ -Issues - - int x[4] = {1, 2, 3, 4}; --> - main::1::x () -> {[0] = 00000000000000000000000000000001 @ [] - [1] = 00000000000000000000000000000010 @ [] - [2] = 00000000000000000000000000000011 @ [] - [3] = 00000000000000000000000000000100 @ [] - } @ [1] - -Problem is that on generation of each element there needs to be a copy -of the instruction location, but this would be a substantial change to the codebase. - -Could be handled as a special case. - --- - -m.age = 10; - -main::1::m () -> {.age=00000000000000000000000000001010 @ [2]} @ [] - -Should be? - -main::1::m () -> {.age=00000000000000000000000000001010 @ [2]} @ [2] - -tl;dr: Copying objects with subelements. \ No newline at end of file diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index e633ec6fb87..b1bb9364c00 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -220,9 +220,11 @@ bool abstract_environmentt::assign( } 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 @@ -549,15 +551,7 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) modified|=object_modified; map[entry.first]=new_object; - if(map[entry.first]->is_top()) - { - // Don't remove TOP items. - //map.erase(entry.first); - //modified=true; -#ifdef DEBUG - std::cout << "Removing " << entry.first.get_identifier() << std::endl; -#endif - } + // Write, even if TOP. } else { @@ -565,28 +559,7 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) } } - // 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;) - { - 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 - // Don't erase - //map.erase(iter++); - //modified=true; - -#ifdef DEBUG - std::cout << "Removing " << iter->first.get_identifier() << std::endl; -#endif - } - else - { - ++iter; - } - } + // Keep TOP items too. return modified; } @@ -726,7 +699,6 @@ void abstract_environmentt::output( } } out << "]"; - // Finish outputting last_written_locations out << "\n"; } @@ -765,3 +737,24 @@ abstract_object_pointert abstract_environmentt::eval_expression( abstract_object_pointert eval_obj=abstract_object_factory(e.type(), e, ns); return eval_obj->expression_transform(e, *this, ns); } + +/*******************************************************************\ + +Function: abstract_environmentt::erase + + Inputs: A symbol to delete from the map + + Outputs: + + Purpose: Delete a symbol from the map. + +\*******************************************************************/ + +void abstract_environmentt::erase(const exprt &expr) +{ + if(expr.id()==ID_symbol) + { + symbol_exprt symbol_expr=to_symbol_expr(expr); + map.erase(symbol_expr); + } +} diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index bd6e9c0fdb0..0be67ce4090 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -37,6 +37,8 @@ class abstract_environmentt const namespacet &ns, bool merge_write); + virtual void erase(const exprt &expr); + virtual abstract_object_pointert abstract_object_factory( const typet &type, const namespacet &ns, diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 60ed305d94d..3cbfb197c47 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -310,10 +310,13 @@ abstract_object_pointert abstract_objectt::merge( // If no modifications, we will return the original pointer out_modifications=result!=op1; - std::vector get_merged_locations = op1->get_new_location_set(op2); - if(get_merged_locations.size() > op1->get_last_written_locations().size()) + locationst get_location_union = op1->get_location_union( + op2->get_last_written_locations()); + // If the union is larger than the initial set, then update. + if(get_location_union.size() > op1->get_last_written_locations().size()) { - result=result->update_last_written_locations(get_merged_locations); + out_modifications=true; + result=result->update_last_written_locations(get_location_union); } return result; @@ -339,4 +342,91 @@ bool abstract_objectt::should_use_base_merge( return is_top() || other->is_bottom() || other->is_top(); } +/*******************************************************************\ + +Function: abstract_objectt::update_last_written_locations + + Inputs: + Set of locations to be written. + + Outputs: + An abstract_object_pointer pointing to the cloned, updated object. + + Purpose: Creates a mutable clone of the current object, and updates + the last written location map with the provided location(s). + + For immutable objects. + +\*******************************************************************/ + +abstract_object_pointert abstract_objectt::update_last_written_locations( + const locationst &locations) const +{ + internal_abstract_object_pointert clone=mutable_clone(); + clone->set_last_written_locations(locations); + clone->update_sub_elements(locations); + return clone; +} + +/*******************************************************************\ + +Function: abstract_objectt::get_location_union + + Inputs: + Set of locations unioned + + Outputs: + The union of the two sets + + Purpose: Takes the location set of the current object, and unions it + with the provided set. + +\*******************************************************************/ + +abstract_objectt::locationst abstract_objectt::get_location_union(const locationst &locations) const +{ + locationst existing_locations=this->get_last_written_locations(); + existing_locations.insert(locations.begin(), locations.end()); + + return existing_locations; +} +/*******************************************************************\ + +Function: abstract_objectt::set_last_written_locations + + Inputs: + Set of locations to be written + + Outputs: + Void + + Purpose: Writes the provided set to the object. + + For mutable objects. + +\*******************************************************************/ + +void abstract_objectt::set_last_written_locations(const locationst &locations) +{ + last_written_locations=locations; +} + +/*******************************************************************\ + +Function: abstract_objectt::get_last_written_locations + + Inputs: + None + + Outputs: + Set of locations for the provided object. + + Purpose: Getter for last_written_locations + +\*******************************************************************/ + +abstract_objectt::locationst abstract_objectt::get_last_written_locations() const +{ + return last_written_locations; +} diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 86a2e327377..a83392f4977 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -31,10 +31,9 @@ #include #include #include - +#include #include - class typet; class constant_exprt; class abstract_environmentt; @@ -100,6 +99,9 @@ class abstract_objectt:public std::enable_shared_from_this virtual void output( std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; + typedef std::set locationst; + + abstract_object_pointert clone() const { return abstract_object_pointert(mutable_clone()); @@ -110,88 +112,20 @@ class abstract_objectt:public std::enable_shared_from_this abstract_object_pointert op2, bool &out_modifications); - - virtual void update_sub_elements(const goto_programt::const_targett &location) - { - return; - } - - - abstract_object_pointert update_last_written_locations(const goto_programt::const_targett &location) const - { - internal_abstract_object_pointert clone=mutable_clone(); - clone->last_written_locations.clear(); - clone->last_written_locations.push_back(location); - clone->update_sub_elements(location); - return clone; - } - - abstract_object_pointert update_last_written_locations(const std::vector &locations) const - { - internal_abstract_object_pointert clone=mutable_clone(); - clone->last_written_locations.clear(); - clone->last_written_locations=locations; - return clone; - } - - // Cheap and dirty diff calculation. - // Moving to (unordered)_sets would allow reliance on built ins. - std::vector get_new_location_set(const abstract_object_pointert &other) const - { - std::vector locations=this->get_last_written_locations(); - std::vector more_locations=other->get_last_written_locations(); - - for(auto add_location:more_locations) - { - bool found=false; - for(auto location:locations) - { - if(location->location_number == add_location->location_number) - { - found=true; - break; - } - } - if(found==false) - { - locations.push_back(add_location); - } - } - - return locations; - } - - - // For mutable - void set_last_written_locations(const abstract_object_pointert &object) - { - last_written_locations.clear(); - for(auto location: object->get_last_written_locations()) - { - last_written_locations.push_back(location); - } - } - - // For mutable - void set_last_written_locations(goto_programt::const_targett &location) - { - last_written_locations.clear(); - last_written_locations.push_back(location); - } - - std::vector get_last_written_locations() const - { - return last_written_locations; - } + abstract_object_pointert update_last_written_locations( + const locationst &locations) const; + void set_last_written_locations(const locationst &locations); + locationst get_last_written_locations() const; private: // To enforce copy-on-write these are private and have read-only accessors typet t; bool bottom; - std::vector last_written_locations; + locationst last_written_locations; abstract_object_pointert abstract_object_merge( const abstract_object_pointert other) const; + locationst get_location_union(const locationst &locations) const; protected: template using internal_sharing_ptrt=std::shared_ptr; @@ -205,6 +139,11 @@ class abstract_objectt:public std::enable_shared_from_this return internal_abstract_object_pointert(new abstract_objectt(*this)); } + virtual void update_sub_elements(const locationst &locations) + { + return; + } + bool top; // The one exception is merge in descendant classes, which needs this diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index e6309b17ce3..ee432d7245c 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -210,7 +210,6 @@ void constant_array_abstract_objectt::output( } } out << "]"; - // End outputting specific last_written_locations out << "\n"; } @@ -436,3 +435,28 @@ bool constant_array_abstract_objectt::eval_index( return false; } } + +/*******************************************************************\ + +Function: constant_array_abstract_objectt::update_sub_elements + + Inputs: + locations - Locations to write + + Outputs: None + + Purpose: Updates write location for sub-elements. + + For example, if a[2] = {5, 6}, this will update + the write location for objects 5 and 6 as well as a. + +\*******************************************************************/ + +void constant_array_abstract_objectt::update_sub_elements( + const locationst &locations) +{ + for(auto &item: map) + { + item.second=item.second->update_last_written_locations(locations); + } +} diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index 7c7fb5be354..d5685aaa20d 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -73,13 +73,7 @@ class constant_array_abstract_objectt:public array_abstract_objectt abstract_object_pointert constant_array_merge( const constant_array_pointert other) const; - virtual void update_sub_elements(const goto_programt::const_targett &location) override - { - for(auto &item: map) - { - item.second=item.second->update_last_written_locations(location); - } - } + virtual void update_sub_elements(const locationst &locations) override; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ARRAY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 0ff00d82fac..339f0acb91d 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -408,3 +408,28 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( } } } + +/*******************************************************************\ + +Function: full_struct_abstract_objectt::update_sub_elements + + Inputs: + locations - Locations to write + + Outputs: None + + Purpose: Updates write location for sub-elements. + + For example, if a=b where a and b are structs, this will + update the write location for components too. + +\*******************************************************************/ + +void full_struct_abstract_objectt::update_sub_elements( + const locationst &locations) +{ + for(auto &item: map) + { + item.second=item.second->update_last_written_locations(locations); + } +} diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 7261e8b2b65..5eafe93951b 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -56,14 +56,7 @@ class full_struct_abstract_objectt:public struct_abstract_objectt typedef std::map struct_mapt; struct_mapt map; - - virtual void update_sub_elements(const goto_programt::const_targett &location) override - { - for(auto &item: map) - { - item.second=item.second->update_last_written_locations(location); - } - } + virtual void update_sub_elements(const locationst &locations) override; abstract_object_pointert merge_constant_structs( constant_struct_pointert other) const; diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 1d3fb763366..03ac64b11ad 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -52,41 +52,32 @@ void variable_sensitivity_domaint::transform( { case DECL: { + const abstract_objectt::locationst write_location={ from }; abstract_object_pointert top_object= abstract_state.abstract_object_factory( to_code_decl(instruction.code).symbol().type(), ns, true) - ->update_last_written_locations(from); + ->update_last_written_locations(write_location); abstract_state.assign( to_code_decl(instruction.code).symbol(), top_object, ns); } - - // Creates a new variable, which should be top - // but we don't store top so ... no action required + // We now store top. break; case DEAD: { - // Assign to top is the same as removing - // TO DO: Erase -// map.erase(to_code_dead(instruction.code).symbol()); -// return true; - - - abstract_object_pointert top_object= - abstract_state.abstract_object_factory( - to_code_dead(instruction.code).symbol().type(), ns, true); -// abstract_state.assign( -// to_code_dead(instruction.code).symbol(), top_object, ns, true); + // Remove symbol from map, the only time this occurs now (keep TOP.) + abstract_state.erase(to_code_dead(instruction.code).symbol()); } break; case ASSIGN: { + // TODO : check return values const code_assignt &inst = to_code_assign(instruction.code); - // TODO : check return values + const abstract_objectt::locationst write_location={ from }; abstract_object_pointert rhs = abstract_state.eval(inst.rhs(), ns) - ->update_last_written_locations(from); + ->update_last_written_locations(write_location); abstract_state.assign(inst.lhs(), rhs, ns); } break; From 2fa69384e98eb8d640d69d07edfa685252dbd2ef Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Mon, 31 Jul 2017 11:19:51 +0100 Subject: [PATCH 146/342] Correction of Thomas's comments. --- .../variable-sensitivity/abstract_enviroment.cpp | 14 +++++--------- .../variable-sensitivity/abstract_enviroment.h | 2 +- .../variable-sensitivity/abstract_object.cpp | 2 +- .../variable-sensitivity/abstract_object.h | 10 +++++----- .../variable_sensitivity_domain.cpp | 7 ++++++- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index b1bb9364c00..893121ae49d 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -257,10 +257,9 @@ bool abstract_environmentt::assign( { map[symbol_expr]=final_value ->update_last_written_locations(value->get_last_written_locations()); - return true; } } - return false; + return true; } /*******************************************************************\ @@ -746,15 +745,12 @@ Function: abstract_environmentt::erase Outputs: - Purpose: Delete a symbol from the map. + Purpose: Delete a symbol from the map. This is necessary if the + symbol falls out of scope and should no longer be tracked. \*******************************************************************/ -void abstract_environmentt::erase(const exprt &expr) +void abstract_environmentt::erase(const symbol_exprt &expr) { - if(expr.id()==ID_symbol) - { - symbol_exprt symbol_expr=to_symbol_expr(expr); - map.erase(symbol_expr); - } + map.erase(expr); } diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 0be67ce4090..d3d82554116 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -37,7 +37,7 @@ class abstract_environmentt const namespacet &ns, bool merge_write); - virtual void erase(const exprt &expr); + void erase(const symbol_exprt &expr); virtual abstract_object_pointert abstract_object_factory( const typet &type, diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 3cbfb197c47..769b673f9bf 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -385,7 +385,7 @@ Function: abstract_objectt::get_location_union abstract_objectt::locationst abstract_objectt::get_location_union(const locationst &locations) const { - locationst existing_locations=this->get_last_written_locations(); + locationst existing_locations=get_last_written_locations(); existing_locations.insert(locations.begin(), locations.end()); return existing_locations; diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index a83392f4977..b86308deab0 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -27,11 +27,12 @@ #include +#include #include #include #include + #include -#include #include class typet; @@ -114,7 +115,6 @@ class abstract_objectt:public std::enable_shared_from_this abstract_object_pointert update_last_written_locations( const locationst &locations) const; - void set_last_written_locations(const locationst &locations); locationst get_last_written_locations() const; private: @@ -139,10 +139,10 @@ class abstract_objectt:public std::enable_shared_from_this return internal_abstract_object_pointert(new abstract_objectt(*this)); } + void set_last_written_locations(const locationst &locations); + virtual void update_sub_elements(const locationst &locations) - { - return; - } + {} bool top; diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 03ac64b11ad..b42ef4addfe 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -66,7 +66,12 @@ void variable_sensitivity_domaint::transform( case DEAD: { // Remove symbol from map, the only time this occurs now (keep TOP.) - abstract_state.erase(to_code_dead(instruction.code).symbol()); + // It should be the case that DEAD only provides symbols for deletion. + const exprt &expr=to_code_dead(instruction.code).symbol(); + if(expr.id()==ID_symbol) + { + abstract_state.erase(to_symbol_expr(expr)); + } } break; From dc47ecf18fac353cdd721e176e8320af79067997 Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Mon, 31 Jul 2017 13:39:44 +0100 Subject: [PATCH 147/342] Extracted the output method for locationst (into environment class, discuss) --- .../abstract_enviroment.cpp | 58 +++++++++++++------ .../abstract_enviroment.h | 3 + .../variable-sensitivity/abstract_object.cpp | 2 +- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 893121ae49d..2ae46a31d15 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -682,23 +682,9 @@ void abstract_environmentt::output( << " (" << ") -> "; entry.second->output(out, ai, ns); - // Start outputting specific last_written_locations - out << " @ ["; - bool comma=false; - for (auto location: entry.second->get_last_written_locations()) - { - if(!comma) - { - out << location->location_number; - comma=true; - } - else - { - out << ", " << location->location_number; - } - } - out << "]"; - + out << " @ "; + output_last_written_locations(out, + entry.second->get_last_written_locations()); out << "\n"; } out << "}\n"; @@ -706,6 +692,44 @@ void abstract_environmentt::output( /*******************************************************************\ +Function: abstract_environmentt::output_last_written_location + + Inputs: + object - the object to read information from + out - the stream to write to + ai - the abstract interpreter that contains this domain + ns - the current namespace + + Outputs: None + + Purpose: Print out all last written locations for a specified + object + +\*******************************************************************/ + +void abstract_environmentt::output_last_written_locations( + std::ostream &out, + const abstract_objectt::locationst &locations) +{ + out << "["; + bool comma=false; + for (auto location: locations) + { + if(!comma) + { + out << location->location_number; + comma=true; + } + else + { + out << ", " << location->location_number; + } + } + out << "]"; +} + +/*******************************************************************\ + Function: abstract_environmentt::verify Inputs: diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index d3d82554116..95f77eb41d8 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -64,6 +64,9 @@ class abstract_environmentt void output( std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; + static void output_last_written_locations( + std::ostream &out, + const abstract_objectt::locationst &locations); bool verify() const; diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 769b673f9bf..a9b235dbcbe 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -364,7 +364,6 @@ abstract_object_pointert abstract_objectt::update_last_written_locations( { internal_abstract_object_pointert clone=mutable_clone(); clone->set_last_written_locations(locations); - clone->update_sub_elements(locations); return clone; } @@ -410,6 +409,7 @@ Function: abstract_objectt::set_last_written_locations void abstract_objectt::set_last_written_locations(const locationst &locations) { last_written_locations=locations; + update_sub_elements(locations); } /*******************************************************************\ From 17155dbe1c510ded702b895f45818e5c7837a028 Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Mon, 31 Jul 2017 15:21:33 +0100 Subject: [PATCH 148/342] To provide a fix for recursive assignments. Recursion into the sub-element should not occur on symbol_exprt updates, this will 'clobber' all sub-elements and destroy all useful data. --- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 3 ++- src/analyses/variable-sensitivity/abstract_object.cpp | 8 +++++--- src/analyses/variable-sensitivity/abstract_object.h | 3 ++- .../constant_array_abstract_object.cpp | 2 +- .../variable-sensitivity/full_struct_abstract_object.cpp | 2 +- .../variable-sensitivity/variable_sensitivity_domain.cpp | 4 ++-- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 2ae46a31d15..1a77e123e01 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -256,7 +256,8 @@ bool abstract_environmentt::assign( if(final_value != map[symbol_expr]) { map[symbol_expr]=final_value - ->update_last_written_locations(value->get_last_written_locations()); + ->update_last_written_locations(value->get_last_written_locations(), + false); } } return true; diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index a9b235dbcbe..8f51444994e 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -316,7 +316,7 @@ abstract_object_pointert abstract_objectt::merge( if(get_location_union.size() > op1->get_last_written_locations().size()) { out_modifications=true; - result=result->update_last_written_locations(get_location_union); + result=result->update_last_written_locations(get_location_union, false); } return result; @@ -360,10 +360,13 @@ Function: abstract_objectt::update_last_written_locations \*******************************************************************/ abstract_object_pointert abstract_objectt::update_last_written_locations( - const locationst &locations) const + const locationst &locations, + bool update_sub_elements) const { internal_abstract_object_pointert clone=mutable_clone(); clone->set_last_written_locations(locations); + if(update_sub_elements) + clone->update_sub_elements(locations); return clone; } @@ -409,7 +412,6 @@ Function: abstract_objectt::set_last_written_locations void abstract_objectt::set_last_written_locations(const locationst &locations) { last_written_locations=locations; - update_sub_elements(locations); } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index b86308deab0..b85ca82e3b9 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -114,7 +114,8 @@ class abstract_objectt:public std::enable_shared_from_this bool &out_modifications); abstract_object_pointert update_last_written_locations( - const locationst &locations) const; + const locationst &locations, + const bool update_sub_elements) const; locationst get_last_written_locations() const; private: diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index ee432d7245c..af96fc71a37 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -457,6 +457,6 @@ void constant_array_abstract_objectt::update_sub_elements( { for(auto &item: map) { - item.second=item.second->update_last_written_locations(locations); + item.second=item.second->update_last_written_locations(locations, true); } } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 339f0acb91d..11b2519d342 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -430,6 +430,6 @@ void full_struct_abstract_objectt::update_sub_elements( { for(auto &item: map) { - item.second=item.second->update_last_written_locations(locations); + item.second=item.second->update_last_written_locations(locations, true); } } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index b42ef4addfe..f59faec8a02 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( abstract_object_pointert top_object= abstract_state.abstract_object_factory( to_code_decl(instruction.code).symbol().type(), ns, true) - ->update_last_written_locations(write_location); + ->update_last_written_locations(write_location, true); abstract_state.assign( to_code_decl(instruction.code).symbol(), top_object, ns); } @@ -82,7 +82,7 @@ void variable_sensitivity_domaint::transform( const abstract_objectt::locationst write_location={ from }; abstract_object_pointert rhs = abstract_state.eval(inst.rhs(), ns) - ->update_last_written_locations(write_location); + ->update_last_written_locations(write_location, true); abstract_state.assign(inst.lhs(), rhs, ns); } break; From 40883bae24f282249aa54ffbf32f1205447fc5f3 Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Tue, 1 Aug 2017 13:10:56 +0100 Subject: [PATCH 149/342] Initial set of tests with manual human inspection. Moved static output method to abstract_object and using output in appropriate sub-classes --- .../sensitivity_dependency_arrays.c | 50 +++++++++++++++ .../test.desc | 41 ++++++++++++ .../sensitivity_dependency_pointers.c | 30 +++++++++ .../test.desc | 37 +++++++++++ .../sensitivity_dependency_structs.c | 59 +++++++++++++++++ .../test.desc | 50 +++++++++++++++ .../sensitivity_dependency_variables.c | 63 +++++++++++++++++++ .../test.desc | 47 ++++++++++++++ .../abstract_enviroment.cpp | 40 +----------- .../abstract_enviroment.h | 3 - .../variable-sensitivity/abstract_object.cpp | 46 ++++++++++++++ .../variable-sensitivity/abstract_object.h | 4 ++ .../constant_array_abstract_object.cpp | 18 +----- .../full_struct_abstract_object.cpp | 19 +----- 14 files changed, 434 insertions(+), 73 deletions(-) create mode 100644 regression/goto-analyzer/sensitivity-last-written-locations-arrays/sensitivity_dependency_arrays.c create mode 100644 regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc create mode 100644 regression/goto-analyzer/sensitivity-last-written-locations-pointers/sensitivity_dependency_pointers.c create mode 100644 regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc create mode 100644 regression/goto-analyzer/sensitivity-last-written-locations-structs/sensitivity_dependency_structs.c create mode 100644 regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc create mode 100644 regression/goto-analyzer/sensitivity-last-written-locations-variables/sensitivity_dependency_variables.c create mode 100644 regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/sensitivity_dependency_arrays.c b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/sensitivity_dependency_arrays.c new file mode 100644 index 00000000000..55458b1aec2 --- /dev/null +++ b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/sensitivity_dependency_arrays.c @@ -0,0 +1,50 @@ +int main() +{ + do_arrays(); +} + +void do_arrays() +{ + int bool_; + int bool_1; + int bool_2; + + int x[2]; + + // Simple variables. + x[0]=10; + x[1]=20; + x[0]=30; + x[1]=40; + x[1]=x[0]; + x[0]=x[1]; + x[0]=5; + x[0]=x[0]+10; + x[1]=10; + + if(bool_) + { + x[0]=20; + } + else + { + x[0]=20; + } + + x[0]=0; + + if(bool_1) + { + x[0]=3; + if(bool_2) + { + x[0]=5; + } + } + else + { + x[0]=7; + } + x[1]=10; + x[0]=20; +} diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc new file mode 100644 index 00000000000..c90e10cd875 --- /dev/null +++ b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc @@ -0,0 +1,41 @@ +CORE +sensitivity_dependency_arrays.c +--variable --arrays --pointers --structs +// Enable multi-line checking +activate-multi-line-match +__CPROVER_threads_exited \(\) -> TOP @ \[14\] +__CPROVER_malloc_is_new_array \(\) -> false @ \[6\] +__CPROVER_dead_object \(\) -> TOP @ \[4\] +__CPROVER_deallocated \(\) -> TOP @ \[5\] +__CPROVER_malloc_object \(\) -> TOP @ \[7\] +__CPROVER_memory_leak \(\) -> TOP @ \[9\] +__CPROVER_rounding_mode \(\) -> 00000000000000000000000000000000 @ \[12\] +__CPROVER_pipe_count \(\) -> 00000000000000000000000000000000 @ \[11\] +__CPROVER_malloc_size \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[8\] +__CPROVER_next_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[10\] +__CPROVER_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[13\] +do_arrays#return_value \(\) -> TOP @ \[49\] +main#return_value \(\) -> TOP @ \[1\] +do_arrays::1::bool_ \(\) -> TOP @ \[16\] +do_arrays::1::bool_1 \(\) -> TOP @ \[17\] +do_arrays::1::bool_2 \(\) -> TOP @ \[18\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000011110 @ \[22\]\n\[1\] = 00000000000000000000000000010100 @ \[21\]\n} @ \[22\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000011110 @ \[22\]\n\[1\] = 00000000000000000000000000101000 @ \[23\]\n} @ \[23\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000011110 @ \[22\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n} @ \[24\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000011110 @ \[25\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n} @ \[25\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000000101 @ \[26\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n} @ \[26\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n} @ \[27\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[28\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[28\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000010100 @ \[30\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[30\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[28\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000010100 @ \[30\, 32\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[30\, 32\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000000000 @ \[34\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[34\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000000011 @ \[36\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[36\] +do_arrays::1::x \(\) -> {\[0\] = TOP @ \[36\, 38\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[36\, 38\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000000000 @ \[34\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[34\] +do_arrays::1::x \(\) -> {\[0\] = TOP @ \[36\, 38\, 41\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[36\, 38\, 41\] +do_arrays::1::x \(\) -> {\[0\] = TOP @ \[36\, 38\, 41\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[36\, 38\, 41\] +do_arrays::1::x \(\) -> {\[0\] = TOP @ \[36\, 38\, 41\]\n\[1\] = 00000000000000000000000000001010 @ \[43\]\n} @ \[43\] +do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000010100 @ \[44\]\n\[1\] = 00000000000000000000000000001010 @ \[43\]\n} @ \[44\] +-- diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/sensitivity_dependency_pointers.c b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/sensitivity_dependency_pointers.c new file mode 100644 index 00000000000..a3904603f7f --- /dev/null +++ b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/sensitivity_dependency_pointers.c @@ -0,0 +1,30 @@ +int main() +{ + do_pointers(); +} + +void do_pointers() +{ + int bool_; + int bool_1; + int bool_2; + + int x=10; + int *x_p; + + int y=20; + int *y_p; + + x_p=&x; + + *x_p=30; + x=40; + + *x_p=*y_p; + x=50; + y_p=&x; + + *x_p=60; + + int j=*y_p; +} diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc new file mode 100644 index 00000000000..4e83206172b --- /dev/null +++ b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc @@ -0,0 +1,37 @@ +CORE +sensitivity_dependency_pointers.c +--variable --arrays --pointers --structs +// Enable multi-line checking +activate-multi-line-match +__CPROVER_threads_exited \(\) -> TOP @ \[14\] +__CPROVER_malloc_is_new_array \(\) -> false @ \[6\] +__CPROVER_dead_object \(\) -> TOP @ \[4\] +__CPROVER_deallocated \(\) -> TOP @ \[5\] +__CPROVER_malloc_object \(\) -> TOP @ \[7\] +__CPROVER_memory_leak \(\) -> TOP @ \[9\] +__CPROVER_rounding_mode \(\) -> 00000000000000000000000000000000 @ \[12\] +__CPROVER_pipe_count \(\) -> 00000000000000000000000000000000 @ \[11\] +__CPROVER_malloc_size \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[8\] +__CPROVER_next_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[10\] +__CPROVER_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[13\] +do_pointers#return_value \(\) -> TOP @ \[42\] +main#return_value \(\) -> TOP @ \[1\] +do_pointers::1::bool_ \(\) -> TOP @ \[16\] +do_pointers::1::bool_1 \(\) -> TOP @ \[17\] +do_pointers::1::bool_2 \(\) -> TOP @ \[18\] +do_pointers::1::x \(\) -> TOP @ \[19\] +do_pointers::1::x \(\) -> 00000000000000000000000000001010 @ \[20\] +do_pointers::1::x_p \(\) -> TOP @ \[21\] +do_pointers::1::y \(\) -> TOP @ \[22\] +do_pointers::1::y \(\) -> 00000000000000000000000000010100 @ \[23\] +do_pointers::1::y_p \(\) -> TOP @ \[24\] +do_pointers::1::x_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[25\] +do_pointers::1::x \(\) -> 00000000000000000000000000011110 @ \[26\] +do_pointers::1::x \(\) -> 00000000000000000000000000101000 @ \[27\] +do_pointers::1::x \(\) -> TOP @ \[28\] +do_pointers::1::x \(\) -> 00000000000000000000000000110010 @ \[29\] +do_pointers::1::y_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[30\] +do_pointers::1::x \(\) -> 00000000000000000000000000111100 @ \[31\] +do_pointers::1::j \(\) -> TOP @ \[32\] +do_pointers::1::j \(\) -> 00000000000000000000000000111100 @ \[33\] +-- diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-structs/sensitivity_dependency_structs.c b/regression/goto-analyzer/sensitivity-last-written-locations-structs/sensitivity_dependency_structs.c new file mode 100644 index 00000000000..7fc2119023e --- /dev/null +++ b/regression/goto-analyzer/sensitivity-last-written-locations-structs/sensitivity_dependency_structs.c @@ -0,0 +1,59 @@ +int main() +{ + do_structs(); +} + +struct Ages { + int x; + int y; +}; + +void do_structs() +{ + int bool_; + int bool_1; + int bool_2; + + struct Ages st; + + // Simple variables. + st.x=10; + st.y=20; + st.x=30; + st.y=40; + st.y=st.x; + st.x=st.y; + st.x=5; + st.x=st.x+10; + st.y=10; + + if(bool_) + { + st.x=20; + } + else + { + st.x=20; + } + + st.x=0; + + if(bool_1) + { + st.x=3; + if(bool_2) + { + st.x=5; + } + } + else + { + st.x=7; + } + st.y=10; + st.x=20; + + struct Ages new_age; + + new_age=st; +} diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc new file mode 100644 index 00000000000..234218b5cb6 --- /dev/null +++ b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc @@ -0,0 +1,50 @@ +CORE +sensitivity_dependency_structs.c +--variable --arrays --pointers --structs +// Enable multi-line checking +activate-multi-line-match +__CPROVER_threads_exited \(\) -> TOP @ \[14\] +__CPROVER_malloc_is_new_array \(\) -> false @ \[6\] +__CPROVER_dead_object \(\) -> TOP @ \[4\] +__CPROVER_deallocated \(\) -> TOP @ \[5\] +__CPROVER_malloc_object \(\) -> TOP @ \[7\] +__CPROVER_memory_leak \(\) -> TOP @ \[9\] +__CPROVER_rounding_mode \(\) -> 00000000000000000000000000000000 @ \[12\] +__CPROVER_pipe_count \(\) -> 00000000000000000000000000000000 @ \[11\] +__CPROVER_malloc_size \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[8\] +__CPROVER_next_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[10\] +__CPROVER_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[13\] +do_structs#return_value \(\) -> TOP @ \[52\] +main#return_value \(\) -> TOP @ \[1\] +do_structs::1::bool_ \(\) -> TOP @ \[16\] +do_structs::1::bool_1 \(\) -> TOP @ \[17\] +do_structs::1::bool_2 \(\) -> TOP @ \[18\] +do_structs::1::st \(\) -> {} @ \[19\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000001010 @ \[20\]} @ \[20\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000001010 @ \[20\]\, .y=00000000000000000000000000010100 @ \[21\]} @ \[21\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000011110 @ \[22\]\, .y=00000000000000000000000000010100 @ \[21\]} @ \[22\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000011110 @ \[22\]\, .y=00000000000000000000000000101000 @ \[23\]} @ \[23\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000011110 @ \[22\]\, .y=00000000000000000000000000011110 @ \[24\]} @ \[24\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000011110 @ \[25\]\, .y=00000000000000000000000000011110 @ \[24\]} @ \[25\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000000101 @ \[26\]\, .y=00000000000000000000000000011110 @ \[24\]} @ \[26\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000011110 @ \[24\]} @ \[27\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[28\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[28\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000010100 @ \[30\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[30\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[28\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000010100 @ \[30\, 32\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[30\, 32\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000010100 @ \[30\, 32\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[30\, 32\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000000000 @ \[34\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[34\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000000000 @ \[34\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[34\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000000011 @ \[36\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[36\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000000011 @ \[36\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[36\] +do_structs::1::st \(\) -> {.x=TOP @ \[36\, 38\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[36\, 38\] +do_structs::1::st \(\) -> {.x=TOP @ \[36\, 38\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[36\, 38\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000000000 @ \[34\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[34\] +do_structs::1::st \(\) -> {.x=TOP @ \[36\, 38\, 41\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[36\, 38\, 41\] +do_structs::1::st \(\) -> {.x=TOP @ \[36\, 38\, 41\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[36\, 38\, 41\] +do_structs::1::st \(\) -> {.x=TOP @ \[36\, 38\, 41\]\, .y=00000000000000000000000000001010 @ \[43\]} @ \[43\] +do_structs::1::st \(\) -> {.x=00000000000000000000000000010100 @ \[44\]\, .y=00000000000000000000000000001010 @ \[43\]} @ \[44\] +do_structs::1::new_age \(\) -> {} @ \[45\] +do_structs::1::new_age \(\) -> {.x=00000000000000000000000000010100 @ \[46\]\, .y=00000000000000000000000000001010 @ \[46\]} @ \[46\] +-- diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-variables/sensitivity_dependency_variables.c b/regression/goto-analyzer/sensitivity-last-written-locations-variables/sensitivity_dependency_variables.c new file mode 100644 index 00000000000..c584f97f49b --- /dev/null +++ b/regression/goto-analyzer/sensitivity-last-written-locations-variables/sensitivity_dependency_variables.c @@ -0,0 +1,63 @@ +int global_x; // Should assign to 0. + +int main() +{ + do_variables(); +} + +void do_variables() +{ + int bool_; + int bool_1; + int bool_2; + + global_x=5; + + // Simple variables. + int x=10; + int y=20; + x=30; + y=40; + y=x; + x=y; + x=5; + x=x+10; + y=10; + + if(bool_) + { + x=20; + } + else + { + x=20; + } + + x=50; + + if(bool_) + { + x=20; + } + else + { + x=30; + } + + x=0; + + if(bool_1) + { + x=3; + if(bool_2) + { + x=5; + } + } + else + { + x=7; + } + y=10; + x=20; +} diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc new file mode 100644 index 00000000000..753fd2c0f75 --- /dev/null +++ b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc @@ -0,0 +1,47 @@ +CORE +sensitivity_dependency_variables.c +--variable --arrays --pointers --structs +// Enable multi-line checking +activate-multi-line-match +__CPROVER_threads_exited \(\) -> TOP @ \[14\] +__CPROVER_malloc_is_new_array \(\) -> false @ \[6\] +__CPROVER_dead_object \(\) -> TOP @ \[4\] +__CPROVER_deallocated \(\) -> TOP @ \[5\] +__CPROVER_malloc_object \(\) -> TOP @ \[7\] +__CPROVER_memory_leak \(\) -> TOP @ \[9\] +__CPROVER_rounding_mode \(\) -> 00000000000000000000000000000000 @ \[12\] +global_x \(\) -> 00000000000000000000000000000000 @ \[15\] +__CPROVER_pipe_count \(\) -> 00000000000000000000000000000000 @ \[11\] +__CPROVER_malloc_size \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[8\] +__CPROVER_next_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[10\] +__CPROVER_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[13\] +do_variables#return_value \(\) -> TOP @ \[59\] +main#return_value \(\) -> TOP @ \[1\] +do_variables::1::bool_ \(\) -> TOP @ \[17\] +do_variables::1::bool_1 \(\) -> TOP @ \[18\] +do_variables::1::bool_2 \(\) -> TOP @ \[19\] +do_variables::1::x \(\) -> TOP @ \[21\] +global_x \(\) -> 00000000000000000000000000000101 @ \[20\] +do_variables::1::x \(\) -> 00000000000000000000000000001010 @ \[22\] +do_variables::1::y \(\) -> TOP @ \[23\] +do_variables::1::y \(\) -> 00000000000000000000000000010100 @ \[24\] +do_variables::1::x \(\) -> 00000000000000000000000000011110 @ \[25\] +do_variables::1::y \(\) -> 00000000000000000000000000101000 @ \[26\] +do_variables::1::y \(\) -> 00000000000000000000000000011110 @ \[27\] +do_variables::1::x \(\) -> 00000000000000000000000000011110 @ \[28\] +do_variables::1::x \(\) -> 00000000000000000000000000000101 @ \[29\] +do_variables::1::x \(\) -> 00000000000000000000000000001111 @ \[30\] +do_variables::1::y \(\) -> 00000000000000000000000000001010 @ \[31\] +do_variables::1::x \(\) -> 00000000000000000000000000010100 @ \[33\] +do_variables::1::x \(\) -> 00000000000000000000000000010100 @ \[33\, 35\] +do_variables::1::x \(\) -> 00000000000000000000000000010100 @ \[33\, 35\] +do_variables::1::x \(\) -> 00000000000000000000000000110010 @ \[37\] +do_variables::1::x \(\) -> 00000000000000000000000000010100 @ \[39\] +do_variables::1::x \(\) -> TOP @ \[39\, 41\] +do_variables::1::x \(\) -> 00000000000000000000000000000000 @ \[43\] +do_variables::1::x \(\) -> 00000000000000000000000000000011 @ \[45\] +do_variables::1::x \(\) -> TOP @ \[45\, 47\] +do_variables::1::x \(\) -> TOP @ \[45\, 47\, 50\] +do_variables::1::y \(\) -> 00000000000000000000000000001010 @ \[52\] +do_variables::1::x \(\) -> 00000000000000000000000000010100 @ \[53\] +-- diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 1a77e123e01..25c05d3fbf7 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -684,7 +684,7 @@ void abstract_environmentt::output( entry.second->output(out, ai, ns); out << " @ "; - output_last_written_locations(out, + entry.second->output_last_written_locations(out, entry.second->get_last_written_locations()); out << "\n"; } @@ -693,44 +693,6 @@ void abstract_environmentt::output( /*******************************************************************\ -Function: abstract_environmentt::output_last_written_location - - Inputs: - object - the object to read information from - out - the stream to write to - ai - the abstract interpreter that contains this domain - ns - the current namespace - - Outputs: None - - Purpose: Print out all last written locations for a specified - object - -\*******************************************************************/ - -void abstract_environmentt::output_last_written_locations( - std::ostream &out, - const abstract_objectt::locationst &locations) -{ - out << "["; - bool comma=false; - for (auto location: locations) - { - if(!comma) - { - out << location->location_number; - comma=true; - } - else - { - out << ", " << location->location_number; - } - } - out << "]"; -} - -/*******************************************************************\ - Function: abstract_environmentt::verify Inputs: diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 95f77eb41d8..d3d82554116 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -64,9 +64,6 @@ class abstract_environmentt void output( std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; - static void output_last_written_locations( - std::ostream &out, - const abstract_objectt::locationst &locations); bool verify() const; diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 8f51444994e..17b869fc90e 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -432,3 +432,49 @@ abstract_objectt::locationst abstract_objectt::get_last_written_locations() cons { return last_written_locations; } + +/*******************************************************************\ + +Function: abstract_objectt::output_last_written_location + + Inputs: + object - the object to read information from + out - the stream to write to + ai - the abstract interpreter that contains this domain + ns - the current namespace + + Outputs: None + + Purpose: Print out all last written locations for a specified + object + +\*******************************************************************/ + +void abstract_objectt::output_last_written_locations( + std::ostream &out, + const abstract_objectt::locationst &locations) +{ + out << "["; + bool comma=false; + + std::set sorted_locations; + for(auto location: locations) + { + sorted_locations.insert(location->location_number); + } + + for (auto location_number: sorted_locations) + { + if(!comma) + { + out << location_number; + comma=true; + } + else + { + out << ", " << location_number; + } + } + out << "]"; +} + diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index b85ca82e3b9..ed4fa5e2ff1 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -118,6 +118,10 @@ class abstract_objectt:public std::enable_shared_from_this const bool update_sub_elements) const; locationst get_last_written_locations() const; + static void output_last_written_locations( + std::ostream &out, + const abstract_objectt::locationst &locations); + private: // To enforce copy-on-write these are private and have read-only accessors typet t; diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index af96fc71a37..96ea74f4f60 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -195,21 +195,9 @@ void constant_array_abstract_objectt::output( entry.second->output(out, ai, ns); // Start outputting specific last_written_locations - out << " @ ["; - bool comma=false; - for(auto location: entry.second->get_last_written_locations()) - { - if(!comma) - { - out << location->location_number; - comma=true; - } - else - { - out << ", " << location->location_number; - } - } - out << "]"; + out << " @ "; + output_last_written_locations(out, + entry.second->get_last_written_locations()); out << "\n"; } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 11b2519d342..4587d44e6c9 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -287,22 +287,9 @@ void full_struct_abstract_objectt::output( entry.second->output(out, ai, ns); // Start outputting specific last_written_locations - out << " @ ["; - bool comma=false; - for(auto loc: entry.second->get_last_written_locations()) - { - if(!comma) - { - out << loc->location_number; - comma=true; - } - else - { - out << ", " << loc->location_number; - } - } - out << "]"; - // End outputting specific last_written_locations + out << " @ "; + output_last_written_locations(out, + entry.second->get_last_written_locations()); } out << "}"; From 1a02d3fd46bc5f8e2e0f4d0ee62e203ef6f097ef Mon Sep 17 00:00:00 2001 From: Daniel Neville Date: Tue, 1 Aug 2017 14:35:27 +0100 Subject: [PATCH 150/342] Correction of formatting (function call over multiple lines). --- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 25c05d3fbf7..61bd80e014c 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -256,8 +256,8 @@ bool abstract_environmentt::assign( if(final_value != map[symbol_expr]) { map[symbol_expr]=final_value - ->update_last_written_locations(value->get_last_written_locations(), - false); + ->update_last_written_locations( + value->get_last_written_locations(), false); } } return true; @@ -684,8 +684,8 @@ void abstract_environmentt::output( entry.second->output(out, ai, ns); out << " @ "; - entry.second->output_last_written_locations(out, - entry.second->get_last_written_locations()); + entry.second->output_last_written_locations( + out, entry.second->get_last_written_locations()); out << "\n"; } out << "}\n"; From 7358d1021eea0498f50a52a68f4663c3bb44f96a Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Tue, 15 Aug 2017 16:07:39 +0100 Subject: [PATCH 151/342] First version of the function that searches two environments for modified symbols. --- .../abstract_enviroment.cpp | 39 ++++++++++ .../abstract_enviroment.h | 5 ++ .../last_written_location.cpp | 71 +++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 unit/analyses/variable-sensitivity/last_written_location.cpp diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 61bd80e014c..c7ed05ea610 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -741,3 +741,42 @@ void abstract_environmentt::erase(const symbol_exprt &expr) { map.erase(expr); } + +/*******************************************************************\ + +Function: abstract_environmentt::environment_diff + + Inputs: Two abstract_environmentt's that need to be intersected for, + so that we can find symbols that have changed between + different domains. + + Outputs: An std::vector containing the symbols that are present in + both environments. + + Purpose: For our implementation of variable sensitivity domains, we + need to be able to efficiently find symbols that have changed + between different domains. To do this, we need to be able + to quickly find which symbols have new written locations, + which we do by finding the intersection between two different + domains (environments). + +\*******************************************************************/ + +std::vector abstract_environmentt::modified_symbols( + const abstract_environmentt &first, const abstract_environmentt &second) +{ + std::vector symbols_diff; + for (const auto &entry : first.map) + { + const auto second_entry = second.map.find(entry.first); + if (second_entry != second.map.end()) + { + if (entry.second->get_last_written_locations() != + second_entry->second->get_last_written_locations()) + { + symbols_diff.push_back(entry.first); + } + } + } + return symbols_diff; +} diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index d3d82554116..41ec22644c7 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -67,6 +68,10 @@ class abstract_environmentt bool verify() const; + static std::vector modified_symbols( + const abstract_environmentt &first, + const abstract_environmentt &second); + protected: bool bottom; diff --git a/unit/analyses/variable-sensitivity/last_written_location.cpp b/unit/analyses/variable-sensitivity/last_written_location.cpp new file mode 100644 index 00000000000..8065ce17034 --- /dev/null +++ b/unit/analyses/variable-sensitivity/last_written_location.cpp @@ -0,0 +1,71 @@ +/*******************************************************************\ + + Module: Write Stack Unit Tests + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +/// \file +/// Unit tests for testing of correct tracking of +/// last written location by objects + +#include "catch.hpp" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +//#include + +SCENARIO("Constructing two environments to make sure we correctly identify modified symbols", + "[core][analyses][variable-sensitivity][last-written-location]") +{ + const irep_idt identifier = "hello"; + auto first_val = symbol_exprt(identifier, integer_typet()); + symbolt first_sym; + first_sym.name = first_val.get_identifier(); + + auto rhs_val = constant_exprt::integer_constant(5); + + const irep_idt second_identifier = "world"; + auto second_val = symbol_exprt(second_identifier, integer_typet()); + symbolt second_sym; + second_sym.name = second_val.get_identifier(); + + symbol_tablet symbol_table; + + symbol_table.add(first_sym); + symbol_table.add(second_sym); + namespacet ns(symbol_table); + + abstract_environmentt env; + + auto first_eval_rhs = env.eval(rhs_val, ns); + auto first_eval_res = env.eval(first_val, ns); + + auto second_eval_res = env.eval(second_val, ns); + auto rhs_val_2 = constant_exprt::integer_constant(10); + auto second_eval_rhs = env.eval(rhs_val_2, ns); + + env.assign(first_val, first_eval_rhs, ns); + env.assign(second_val, second_eval_rhs, ns); + + abstract_environmentt second_env; + second_env.assign(first_val, first_eval_rhs, ns); + second_env.assign(second_val, second_eval_rhs, ns); + + auto changed_vals = abstract_environmentt::modified_symbols( + env, second_env); + for (auto const &val : changed_vals) { + std::cout << val.pretty() << std::endl; + } +} From bb6a829e84829e6731b73aed296fe6684f10733b Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Wed, 16 Aug 2017 14:41:08 +0100 Subject: [PATCH 152/342] [WIP] Added more tests. --- unit/Makefile | 1 + .../last_written_location.cpp | 115 +++++++++++++----- 2 files changed, 86 insertions(+), 30 deletions(-) diff --git a/unit/Makefile b/unit/Makefile index 138bbe121e3..1d11afcf900 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -18,6 +18,7 @@ SRC += analyses/ai/ai.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 \ + analyses/variable-sensitivity/last_written_location.cpp \ analyses/variable-sensitivity/write_stack.cpp \ ansi-c/max_malloc_size.cpp \ ansi-c/type2name.cpp \ diff --git a/unit/analyses/variable-sensitivity/last_written_location.cpp b/unit/analyses/variable-sensitivity/last_written_location.cpp index 8065ce17034..4f3d272714e 100644 --- a/unit/analyses/variable-sensitivity/last_written_location.cpp +++ b/unit/analyses/variable-sensitivity/last_written_location.cpp @@ -29,43 +29,98 @@ SCENARIO("Constructing two environments to make sure we correctly identify modified symbols", "[core][analyses][variable-sensitivity][last-written-location]") { - const irep_idt identifier = "hello"; - auto first_val = symbol_exprt(identifier, integer_typet()); - symbolt first_sym; - first_sym.name = first_val.get_identifier(); + GIVEN("Two identifiers that contain integer values") + { + const irep_idt identifier = "hello"; + auto first_val = symbol_exprt(identifier, integer_typet()); + symbolt first_sym; + first_sym.name = first_val.get_identifier(); - auto rhs_val = constant_exprt::integer_constant(5); + auto rhs_val = constant_exprt::integer_constant(5); - const irep_idt second_identifier = "world"; - auto second_val = symbol_exprt(second_identifier, integer_typet()); - symbolt second_sym; - second_sym.name = second_val.get_identifier(); + const irep_idt second_identifier = "world"; + auto second_val = symbol_exprt(second_identifier, integer_typet()); + symbolt second_sym; + second_sym.name = second_val.get_identifier(); - symbol_tablet symbol_table; + symbol_tablet symbol_table; - symbol_table.add(first_sym); - symbol_table.add(second_sym); - namespacet ns(symbol_table); - - abstract_environmentt env; - - auto first_eval_rhs = env.eval(rhs_val, ns); - auto first_eval_res = env.eval(first_val, ns); + symbol_table.add(first_sym); + symbol_table.add(second_sym); + namespacet ns(symbol_table); + + WHEN("The identifiers get inserted into two environments") + { + abstract_environmentt env; + + auto first_eval_rhs = env.eval(rhs_val, ns); + auto first_eval_res = env.eval(first_val, ns); + + auto second_eval_res = env.eval(second_val, ns); + auto rhs_val_2 = constant_exprt::integer_constant(10); + auto second_eval_rhs = env.eval(rhs_val_2, ns); + + env.assign(first_val, first_eval_rhs, ns); + env.assign(second_val, second_eval_rhs, ns); + + abstract_environmentt second_env; + second_env.assign(first_val, first_eval_rhs, ns); + second_env.assign(second_val, second_eval_rhs, ns); + + THEN("The modified symbols between the two domains should be none") { + auto changed_vals = abstract_environmentt::modified_symbols( + env, second_env); + REQUIRE(changed_vals.size() == 0); + } + } + } + GIVEN("Two identifiers that contain integer values") + { + const irep_idt identifier = "hello"; + auto first_val = symbol_exprt(identifier, integer_typet()); + symbolt first_sym; + first_sym.name = first_val.get_identifier(); + + auto rhs_val = constant_exprt::integer_constant(5); - auto second_eval_res = env.eval(second_val, ns); - auto rhs_val_2 = constant_exprt::integer_constant(10); - auto second_eval_rhs = env.eval(rhs_val_2, ns); + const irep_idt second_identifier = "world"; + auto second_val = symbol_exprt(second_identifier, integer_typet()); + symbolt second_sym; + second_sym.name = second_val.get_identifier(); - env.assign(first_val, first_eval_rhs, ns); - env.assign(second_val, second_eval_rhs, ns); + symbol_tablet symbol_table; + + symbol_table.add(first_sym); + symbol_table.add(second_sym); + namespacet ns(symbol_table); + + WHEN("The identifiers get inserted into two environments, but one of \ + them has a different value in one of the environments") + { + abstract_environmentt env; + + auto first_eval_rhs = env.eval(rhs_val, ns); + auto first_eval_res = env.eval(first_val, ns); + + auto second_eval_res = env.eval(second_val, ns); + auto rhs_val_2 = constant_exprt::integer_constant(10); + auto second_eval_rhs = env.eval(rhs_val_2, ns); + + env.assign(first_val, first_eval_rhs, ns); + env.assign(second_val, second_eval_rhs, ns); + + auto rhs_val_3 = constant_exprt::integer_constant(20); - abstract_environmentt second_env; - second_env.assign(first_val, first_eval_rhs, ns); - second_env.assign(second_val, second_eval_rhs, ns); + abstract_environmentt second_env; + auto new_rhs_val = second_env.eval(rhs_val_3, ns); + second_env.assign(first_val, first_eval_rhs, ns); + second_env.assign(second_val, new_rhs_val, ns); - auto changed_vals = abstract_environmentt::modified_symbols( - env, second_env); - for (auto const &val : changed_vals) { - std::cout << val.pretty() << std::endl; + THEN("The modified symbols between the two domains should be none") { + auto changed_vals = abstract_environmentt::modified_symbols( + env, second_env); + REQUIRE(changed_vals.size() == 0); + } + } } } From 4572d1f9a67779ea18b0347e03c46b3f74ec5170 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 16 Aug 2017 17:43:06 +0100 Subject: [PATCH 153/342] Temporary commit for using the modified values --- .../main.c | 65 +++++++++++++++ .../test.desc | 3 + .../abstract_enviroment.cpp | 82 ++++++++++++++++--- .../variable-sensitivity/abstract_object.h | 1 + .../variable_sensitivity_domain.cpp | 7 ++ 5 files changed, 145 insertions(+), 13 deletions(-) create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c new file mode 100644 index 00000000000..d5a94d7f74c --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c @@ -0,0 +1,65 @@ +#include + +int global; + +void simple_function() +{ + int j = 0; +} + +void pointer_function(int * write_to, int value) +{ + *write_to=value; +} + +void modify_global_function(int new_val) +{ + global = new_val; +} + +void simple_test() +{ + int i = 0; + global = 0; + simple_function(); + __CPROVER_assert(i==0, "i==0"); + __CPROVER_assert(global==0, "global==0"); + + i = 1; + global = 2; + simple_function(); + __CPROVER_assert(i==1, "i==1") ; + __CPROVER_assert(global==2, "global==2") ; +} + +void pointer_test() +{ + int i = 0; + int j = 1; + simple_function(&i, 10); + __CPROVER_assert(j==1, "j==1"); + __CPROVER_assert(i==10, "i==10"); + + pointer_function(&i, 10); + + __CPROVER_assert(j==1, "j==1"); + __CPROVER_assert(i==10, "i==10"); + + pointer_function(&i, 11); + + __CPROVER_assert(j==1, "j==1"); + __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function +} + +void global_test() +{ + global = 0; + modify_global_function(42); + __CPROVER_assert(global==42, "global==42"); + + modify_global_function(50); + __CPROVER_assert(global==50, "global==50"); // unknown since new_val will be top +} + + + diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc new file mode 100644 index 00000000000..1ada111c8e8 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc @@ -0,0 +1,3 @@ +CORE +main.c +--function simple \ No newline at end of file diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index c7ed05ea610..961a046c795 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -514,6 +514,9 @@ Function: abstract_environmentt::merge \*******************************************************************/ + +#include + bool abstract_environmentt::merge(const abstract_environmentt &env) { // Use the sharing_map's "iterative over all differences" functionality @@ -534,6 +537,14 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) } else { + std::vector modified_symbols= + abstract_environmentt::modified_symbols(*this, env); + + for(const symbol_exprt &x : modified_symbols) + { + std::cout << x.get_identifier() << std::endl; + } + // 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; @@ -541,17 +552,24 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) { if(map.find(entry.first)!=map.end()) { - bool object_modified=false; - abstract_object_pointert new_object= - abstract_objectt::merge( - map[entry.first], - entry.second, - object_modified); - - modified|=object_modified; - map[entry.first]=new_object; - - // Write, even if TOP. + if( + std::find( + modified_symbols.begin(), + modified_symbols.end(), + entry.first)!=modified_symbols.cend()) + { + bool object_modified=false; + abstract_object_pointert new_object= + abstract_objectt::merge( + map[entry.first], + entry.second, + object_modified); + + modified|=object_modified; + map[entry.first]=new_object; + + // Write, even if TOP. + } } else { @@ -771,9 +789,47 @@ std::vector abstract_environmentt::modified_symbols( const auto second_entry = second.map.find(entry.first); if (second_entry != second.map.end()) { - if (entry.second->get_last_written_locations() != - second_entry->second->get_last_written_locations()) + // for the last written write locations to match + // each location in one must be equal to precisely one location + // in the other + // Since a set can assume at most one match + + const auto location_matcher= + [&]( + goto_programt::const_targett instruction, + goto_programt::const_targett other_instruction) + { + return other_instruction->location_number==instruction->location_number; + }; + + + const abstract_objectt::locationst &a=entry.second->get_last_written_locations(); + const abstract_objectt::locationst &b=second_entry->second->get_last_written_locations(); + + abstract_objectt::locationst intersection; + std::set_intersection( + a.cbegin(), + a.cend(), + b.cbegin(), + b.cend(), + std::inserter(intersection, intersection.end()), + location_matcher); + bool all_matched= + intersection.size()==a.size() && intersection.size()==b.size(); + + if (!all_matched) { + goto_programt::instructiont last_written_locations=**entry.second->get_last_written_locations().begin(); + goto_programt::instructiont last_written_locations2=**second_entry->second->get_last_written_locations().begin(); + + if(last_written_locations.source_location==last_written_locations2.source_location) + { + std::cout << + entry.first.get_identifier() << ":" << + last_written_locations.location_number << " vs" + << last_written_locations2.location_number << std::endl; + } + symbols_diff.push_back(entry.first); } } diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index ed4fa5e2ff1..a9561a82677 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -68,6 +68,7 @@ class namespacet; * merge then it merges, otherwise it calls the parent merge. */ + template using sharing_ptrt=std::shared_ptr; // NOLINT(*) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index f59faec8a02..cea907a1a06 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -17,6 +17,8 @@ Date: April 2016 #include "variable_sensitivity_domain.h" #include +#define DEBUG + #ifdef DEBUG #include #endif @@ -276,6 +278,11 @@ bool variable_sensitivity_domaint::merge( << to->location_number << std::endl; #endif + if(from->location_number==13 && to->location_number==58) + { + + } + // Use the abstract_environment merge bool any_changes=abstract_state.merge(b.abstract_state); From c063eaf853b1699f6b50bc20c6569232ce290265 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 17 Aug 2017 14:35:19 +0100 Subject: [PATCH 154/342] Implementing a write_stack to represent writing to a addressable location More random changes --- .../main.c | 14 ++-- .../abstract_enviroment.cpp | 64 ++++++++++++++----- .../variable_sensitivity_domain.cpp | 4 +- .../last_written_location.cpp | 2 +- 4 files changed, 60 insertions(+), 24 deletions(-) diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c index d5a94d7f74c..108f39b5472 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c @@ -2,7 +2,7 @@ int global; -void simple_function() +void simple_function(void) { int j = 0; } @@ -36,19 +36,25 @@ void pointer_test() { int i = 0; int j = 1; - simple_function(&i, 10); + pointer_function(&i, 10); + __CPROVER_assert(j==1, "j==1"); __CPROVER_assert(i==10, "i==10"); + j=2; pointer_function(&i, 10); - __CPROVER_assert(j==1, "j==1"); + __CPROVER_assert(j==2, "j==2"); __CPROVER_assert(i==10, "i==10"); + j=3; pointer_function(&i, 11); - __CPROVER_assert(j==1, "j==1"); + __CPROVER_assert(j==3, "j==3"); __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function + + j=4; + pointer_function(&i, 11); } void global_test() diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 961a046c795..be28e5a70df 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -786,7 +786,7 @@ std::vector abstract_environmentt::modified_symbols( std::vector symbols_diff; for (const auto &entry : first.map) { - const auto second_entry = second.map.find(entry.first); + const auto &second_entry = second.map.find(entry.first); if (second_entry != second.map.end()) { // for the last written write locations to match @@ -794,42 +794,72 @@ std::vector abstract_environmentt::modified_symbols( // in the other // Since a set can assume at most one match +#if 0 const auto location_matcher= [&]( goto_programt::const_targett instruction, goto_programt::const_targett other_instruction) { - return other_instruction->location_number==instruction->location_number; + return other_instruction->location_numberlocation_number; }; +#endif const abstract_objectt::locationst &a=entry.second->get_last_written_locations(); const abstract_objectt::locationst &b=second_entry->second->get_last_written_locations(); + class location_ordert + { + public: + bool operator()( + goto_programt::const_targett instruction, + goto_programt::const_targett other_instruction) + { + return instruction->location_numberlocation_number; + } + }; + + typedef std::set sorted_locationst; + + sorted_locationst lhs_location; + for(const auto &entry:a) + { + lhs_location.insert(entry); + } + + + sorted_locationst rhs_location; + for(const auto &entry:a) + { + rhs_location.insert(entry); + } + abstract_objectt::locationst intersection; std::set_intersection( - a.cbegin(), - a.cend(), - b.cbegin(), - b.cend(), + lhs_location.cbegin(), + lhs_location.cend(), + rhs_location.cbegin(), + rhs_location.cend(), std::inserter(intersection, intersection.end()), - location_matcher); + location_ordert()); bool all_matched= intersection.size()==a.size() && intersection.size()==b.size(); - if (!all_matched) + std::cout << entry.first.get_identifier() << ": {"; + for(const auto &entry:lhs_location) { - goto_programt::instructiont last_written_locations=**entry.second->get_last_written_locations().begin(); - goto_programt::instructiont last_written_locations2=**second_entry->second->get_last_written_locations().begin(); + std::cout << entry->location_number << ", "; + } - if(last_written_locations.source_location==last_written_locations2.source_location) - { - std::cout << - entry.first.get_identifier() << ":" << - last_written_locations.location_number << " vs" - << last_written_locations2.location_number << std::endl; - } + std::cout << " } vs { "; + for(const auto &entry:rhs_location) + { + std::cout << entry->location_number << ", "; + } + std::cout << " }" << std::endl; + if (!all_matched) + { symbols_diff.push_back(entry.first); } } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index cea907a1a06..0a4a1eafd71 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -278,7 +278,7 @@ bool variable_sensitivity_domaint::merge( << to->location_number << std::endl; #endif - if(from->location_number==13 && to->location_number==58) + if(from->location_number==43) { } @@ -475,7 +475,7 @@ void variable_sensitivity_domaint::transform_function_call( // Evaluate the expression that is being // passed into the function call (called_arg) - abstract_object_pointert param_val=abstract_state.eval(called_arg, ns); + abstract_object_pointert param_val=abstract_state.eval(called_arg, ns)->update_last_written_locations({ from }, true); // Assign the evaluated value to the symbol associated with the // parameter of the function diff --git a/unit/analyses/variable-sensitivity/last_written_location.cpp b/unit/analyses/variable-sensitivity/last_written_location.cpp index 4f3d272714e..ba28999bb41 100644 --- a/unit/analyses/variable-sensitivity/last_written_location.cpp +++ b/unit/analyses/variable-sensitivity/last_written_location.cpp @@ -119,7 +119,7 @@ SCENARIO("Constructing two environments to make sure we correctly identify modif THEN("The modified symbols between the two domains should be none") { auto changed_vals = abstract_environmentt::modified_symbols( env, second_env); - REQUIRE(changed_vals.size() == 0); + REQUIRE(changed_vals.size() == 0); } } } From 33f29f21284c06c33c2e6ab9bfd31b7f743fae44 Mon Sep 17 00:00:00 2001 From: thk123 Date: Fri, 18 Aug 2017 09:44:34 +0100 Subject: [PATCH 155/342] Another temp checkin of where we've got to --- .../variable-sensitivity/abstract_enviroment.cpp | 7 +++---- .../variable_sensitivity_domain.cpp | 8 ++++++++ .../variable-sensitivity/variable_sensitivity_domain.h | 10 ++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index be28e5a70df..167059b8f9e 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -815,7 +815,7 @@ std::vector abstract_environmentt::modified_symbols( goto_programt::const_targett instruction, goto_programt::const_targett other_instruction) { - return instruction->location_numberlocation_number; + return instruction->location_number>other_instruction->location_number; } }; @@ -829,7 +829,7 @@ std::vector abstract_environmentt::modified_symbols( sorted_locationst rhs_location; - for(const auto &entry:a) + for(const auto &entry:b) { rhs_location.insert(entry); } @@ -842,8 +842,7 @@ std::vector abstract_environmentt::modified_symbols( rhs_location.cend(), std::inserter(intersection, intersection.end()), location_ordert()); - bool all_matched= - intersection.size()==a.size() && intersection.size()==b.size(); + bool all_matched=intersection.size()==a.size(); std::cout << entry.first.get_identifier() << ": {"; for(const auto &entry:lhs_location) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 0a4a1eafd71..185a6d28c70 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -143,6 +143,8 @@ void variable_sensitivity_domaint::transform( abstract_state.abstract_object_factory(param.type(), ns, true, false), ns); } + + break; } @@ -181,6 +183,8 @@ void variable_sensitivity_domaint::transform( throw "unrecognised instruction type"; } + output(std::cout, ai, ns); + assert(abstract_state.verify()); } @@ -285,6 +289,7 @@ bool variable_sensitivity_domaint::merge( // Use the abstract_environment merge bool any_changes=abstract_state.merge(b.abstract_state); + pre_function_state=b.pre_function_state; assert(abstract_state.verify()); return any_changes; @@ -395,6 +400,9 @@ void variable_sensitivity_domaint::transform_function_call( const code_function_callt &function_call=to_code_function_call(from->code); const exprt &function=function_call.function(); + pre_function_state=abstract_state; + + const locationt next=std::next(from); if(function.id()==ID_symbol) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index d901791f767..f21cbce2af1 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -92,6 +92,8 @@ class variable_sensitivity_domaint:public ai_domain_baset const ai_baset &ai, const namespacet &ns) const override; + void output(std::ostream &out) const; + virtual bool merge( const variable_sensitivity_domaint &b, locationt from, @@ -104,6 +106,11 @@ class variable_sensitivity_domaint:public ai_domain_baset bool is_bottom() const override; bool is_top() const override; + virtual std::vector get_modified_symbols(const variable_sensitivity_domaint &other) + { + return abstract_environmentt::modified_symbols(abstract_state, other.abstract_state); + } + private: void transform_function_call( locationt from, @@ -114,6 +121,9 @@ class variable_sensitivity_domaint:public ai_domain_baset bool ignore_function_call_transform(const irep_idt &function_id) const; abstract_environmentt abstract_state; + + const ai_domain_baset &pre_function_state; + const ai_domain_baset &head_function_state; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H From 4dc4c44892ee2a90c8fa41754d90e53e0672635f Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 21 Aug 2017 11:14:10 +0100 Subject: [PATCH 156/342] Adding get_modified_symbols to other domainTs --- .../variable-sensitivity/variable_sensitivity_domain.cpp | 4 ---- .../variable-sensitivity/variable_sensitivity_domain.h | 5 +---- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 185a6d28c70..a8af5eb9942 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -289,7 +289,6 @@ bool variable_sensitivity_domaint::merge( // Use the abstract_environment merge bool any_changes=abstract_state.merge(b.abstract_state); - pre_function_state=b.pre_function_state; assert(abstract_state.verify()); return any_changes; @@ -400,9 +399,6 @@ void variable_sensitivity_domaint::transform_function_call( const code_function_callt &function_call=to_code_function_call(from->code); const exprt &function=function_call.function(); - pre_function_state=abstract_state; - - const locationt next=std::next(from); if(function.id()==ID_symbol) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index f21cbce2af1..713ef789ee3 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -106,7 +106,7 @@ class variable_sensitivity_domaint:public ai_domain_baset bool is_bottom() const override; bool is_top() const override; - virtual std::vector get_modified_symbols(const variable_sensitivity_domaint &other) + virtual std::vector get_modified_symbols(const variable_sensitivity_domaint &other) const { return abstract_environmentt::modified_symbols(abstract_state, other.abstract_state); } @@ -121,9 +121,6 @@ class variable_sensitivity_domaint:public ai_domain_baset bool ignore_function_call_transform(const irep_idt &function_id) const; abstract_environmentt abstract_state; - - const ai_domain_baset &pre_function_state; - const ai_domain_baset &head_function_state; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H From 9479a93b2e08239e5f4ff7f0ffee7f043882736e Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 21 Aug 2017 11:32:44 +0100 Subject: [PATCH 157/342] Restored the correct modified symbols We can now see reliably which symbols have been modified at the end of a function call. --- 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 167059b8f9e..9eacbf60285 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -842,7 +842,8 @@ std::vector abstract_environmentt::modified_symbols( rhs_location.cend(), std::inserter(intersection, intersection.end()), location_ordert()); - bool all_matched=intersection.size()==a.size(); + bool all_matched=intersection.size()==a.size() && + intersection.size()==b.size(); std::cout << entry.first.get_identifier() << ": {"; for(const auto &entry:lhs_location) From 6608e83e4b789a67a32dbd30f2bf355b8200ed2b Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Mon, 21 Aug 2017 15:24:36 +0100 Subject: [PATCH 158/342] [WIP] Added the restore domain function. --- .../variable_sensitivity_domain.cpp | 11 +++++++++++ .../variable_sensitivity_domain.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index a8af5eb9942..24a4931f4e1 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -531,3 +531,14 @@ bool variable_sensitivity_domaint::ignore_function_call_transform( return ignored_internal_function.find(function_id)!= ignored_internal_function.cend(); } + +void variable_sensitivity_domaint::restore_domain(std::vector modified_symbols, + variable_sensitivity_domaint &target, + const namespacet &ns) const +{ + for (const auto &symbol : modified_symbols) + { + auto value = abstract_state.eval(symbol, ns); + target.abstract_state.assign(symbol, value, ns); + } +} \ No newline at end of file diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 713ef789ee3..b321f5d8692 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -111,6 +111,9 @@ class variable_sensitivity_domaint:public ai_domain_baset return abstract_environmentt::modified_symbols(abstract_state, other.abstract_state); } + virtual void restore_domain(std::vector modified_symbols, + variable_sensitivity_domaint &target, const namespacet &ns) const; + private: void transform_function_call( locationt from, From 5702a325b579cd793245560c65094ae29e0c6baa Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 21 Aug 2017 15:57:10 +0100 Subject: [PATCH 159/342] Use the restore_domain function to do context sensitive func return --- .../main.c | 5 ++- .../abstract_enviroment.cpp | 40 +++++++------------ 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c index 108f39b5472..26698bb389e 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c @@ -54,7 +54,10 @@ void pointer_test() __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function j=4; - pointer_function(&i, 11); + pointer_function(&i, 478); + + __CPROVER_assert(j==4, "j==3"); + __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function } void global_test() diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 9eacbf60285..f5b73f5ffc0 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -537,14 +537,6 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) } else { - std::vector modified_symbols= - abstract_environmentt::modified_symbols(*this, env); - - for(const symbol_exprt &x : modified_symbols) - { - std::cout << x.get_identifier() << std::endl; - } - // 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; @@ -552,24 +544,20 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) { if(map.find(entry.first)!=map.end()) { - if( - std::find( - modified_symbols.begin(), - modified_symbols.end(), - entry.first)!=modified_symbols.cend()) - { - bool object_modified=false; - abstract_object_pointert new_object= - abstract_objectt::merge( - map[entry.first], - entry.second, - object_modified); - - modified|=object_modified; - map[entry.first]=new_object; - - // Write, even if TOP. - } + bool object_modified=false; + abstract_object_pointert new_object= + abstract_objectt::merge( + map[entry.first], + entry.second, + object_modified); + + modified|=object_modified; + map[entry.first]=new_object; + + // Write, even if TOP. Since we now track the write locations of an + // object, even if it is TOP we still have useful information about it. + // This is used for when we want to find out what has been modified + // between two locations (even if we don't know what has been written). } else { From 90b6e6b7436fccd50f60ef83a67d80934abd9008 Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Tue, 22 Aug 2017 13:28:45 +0100 Subject: [PATCH 160/342] Added a test for the variable sensitivity assign aware merge, for the function pointer_function. --- .../main.c | 2 +- .../test.desc | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c index 26698bb389e..eaddbedf304 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c @@ -56,7 +56,7 @@ void pointer_test() j=4; pointer_function(&i, 478); - __CPROVER_assert(j==4, "j==3"); + __CPROVER_assert(j==4, "j==4"); __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function } diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc index 1ada111c8e8..1182dddcb3b 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc @@ -1,3 +1,14 @@ CORE main.c ---function simple \ No newline at end of file +--function pointer_test --variable --pointers --arrays --structs --verify +^EXIT=0$ +^SIGNAL=0$ +^\[pointer_test.assertion.1\] file main.c line 41 function pointer_test, j==1: Success$ +^\[pointer_test.assertion.2\] file main.c line 42 function pointer_test, i==10: Success$ +^\[pointer_test.assertion.3\] file main.c line 47 function pointer_test, j==2: Success$ +^\[pointer_test.assertion.4\] file main.c line 48 function pointer_test, i==10: Success$ +^\[pointer_test.assertion.5\] file main.c line 53 function pointer_test, j==3: Success$ +^\[pointer_test.assertion.6\] file main.c line 54 function pointer_test, i==11: Unknown$ +^\[pointer_test.assertion.7\] file main.c line 59 function pointer_test, j==4: Success$ +^\[pointer_test.assertion.8\] file main.c line 60 function pointer_test, i==11: Unknown$ +-- \ No newline at end of file From 73db5946f2fbc0e46ae9bf668e8a4d90b17cffad Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Tue, 22 Aug 2017 13:35:00 +0100 Subject: [PATCH 161/342] Added more tests for variable sensitivity assign aware merge for function simple_test. --- .../main.c | 74 +++++++++++++++++++ .../test.desc | 11 +++ 2 files changed, 85 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/main.c new file mode 100644 index 00000000000..eaddbedf304 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/main.c @@ -0,0 +1,74 @@ +#include + +int global; + +void simple_function(void) +{ + int j = 0; +} + +void pointer_function(int * write_to, int value) +{ + *write_to=value; +} + +void modify_global_function(int new_val) +{ + global = new_val; +} + +void simple_test() +{ + int i = 0; + global = 0; + simple_function(); + __CPROVER_assert(i==0, "i==0"); + __CPROVER_assert(global==0, "global==0"); + + i = 1; + global = 2; + simple_function(); + __CPROVER_assert(i==1, "i==1") ; + __CPROVER_assert(global==2, "global==2") ; +} + +void pointer_test() +{ + int i = 0; + int j = 1; + pointer_function(&i, 10); + + __CPROVER_assert(j==1, "j==1"); + __CPROVER_assert(i==10, "i==10"); + + j=2; + pointer_function(&i, 10); + + __CPROVER_assert(j==2, "j==2"); + __CPROVER_assert(i==10, "i==10"); + + j=3; + pointer_function(&i, 11); + + __CPROVER_assert(j==3, "j==3"); + __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function + + j=4; + pointer_function(&i, 478); + + __CPROVER_assert(j==4, "j==4"); + __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function +} + +void global_test() +{ + global = 0; + modify_global_function(42); + __CPROVER_assert(global==42, "global==42"); + + modify_global_function(50); + __CPROVER_assert(global==50, "global==50"); // unknown since new_val will be top +} + + + diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc new file mode 100644 index 00000000000..50a8e8c90e2 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc @@ -0,0 +1,11 @@ +CORE +main.c +--function simple_test --variable --pointers --arrays --structs --verify +^EXIT=0$ +^SIGNAL=0$ +^\[simple_test.assertion.1\] file main.c line 25 function simple_test, i==0: Success$ +^\[simple_test.assertion.2\] file main.c line 26 function simple_test, global==0: Success$ +^\[simple_test.assertion.3\] file main.c line 31 function simple_test, i==1: Success$ +^\[simple_test.assertion.4\] file main.c line 32 function simple_test, global==2: Success$ + +-- \ No newline at end of file From 89d5c0b763e84e885a94428a9c3c1b8239248b4f Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Tue, 22 Aug 2017 13:41:25 +0100 Subject: [PATCH 162/342] Added more tests for variable sensitivity assign aware merge for function global_test. --- .../main.c | 74 +++++++++++++++++++ .../test.desc | 8 ++ 2 files changed, 82 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/main.c new file mode 100644 index 00000000000..eaddbedf304 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/main.c @@ -0,0 +1,74 @@ +#include + +int global; + +void simple_function(void) +{ + int j = 0; +} + +void pointer_function(int * write_to, int value) +{ + *write_to=value; +} + +void modify_global_function(int new_val) +{ + global = new_val; +} + +void simple_test() +{ + int i = 0; + global = 0; + simple_function(); + __CPROVER_assert(i==0, "i==0"); + __CPROVER_assert(global==0, "global==0"); + + i = 1; + global = 2; + simple_function(); + __CPROVER_assert(i==1, "i==1") ; + __CPROVER_assert(global==2, "global==2") ; +} + +void pointer_test() +{ + int i = 0; + int j = 1; + pointer_function(&i, 10); + + __CPROVER_assert(j==1, "j==1"); + __CPROVER_assert(i==10, "i==10"); + + j=2; + pointer_function(&i, 10); + + __CPROVER_assert(j==2, "j==2"); + __CPROVER_assert(i==10, "i==10"); + + j=3; + pointer_function(&i, 11); + + __CPROVER_assert(j==3, "j==3"); + __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function + + j=4; + pointer_function(&i, 478); + + __CPROVER_assert(j==4, "j==4"); + __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function +} + +void global_test() +{ + global = 0; + modify_global_function(42); + __CPROVER_assert(global==42, "global==42"); + + modify_global_function(50); + __CPROVER_assert(global==50, "global==50"); // unknown since new_val will be top +} + + + diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc new file mode 100644 index 00000000000..2f9590aff78 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--function global_test --variable --pointers --arrays --structs --verify +^EXIT=0$ +^SIGNAL=0$ +^\[global_test.assertion.1\] file main.c line 67 function global_test, global==42: Success$ +^\[global_test.assertion.2\] file main.c line 70 function global_test, global==50: Unknown$ +-- \ No newline at end of file From eac3fe18d5f9065e5b7c041727dedc1f7d00ef8a Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Tue, 22 Aug 2017 15:23:58 +0100 Subject: [PATCH 163/342] Added a basic file for array tests. Need thomas to config its validity before I author the test.desc --- .../main.c | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c new file mode 100644 index 00000000000..04c6dd7dcab --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c @@ -0,0 +1,35 @@ +int a[10]; + +int c[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + +void param_test(int array[]) +{ + array[1] = 5; + // TODO: This is marked as "unknown" when running analysis of param_test and global_test. Doesn't seem correct + // as array[1] is being assigned one line above? + __CPROVER_assert(a[1]==5, "a[1]==5"); +} + +void global_test() +{ + a[2] = 6; + __CPROVER_assert(a[2]==6, "a[2]==6"); + c[8] = 15; + __CPROVER_assert(c[8]==15, "c[8]==15"); + // TODO: This is marked as "unknown" when running analysis of global_test. CORRECT? + __CPROVER_assert(c[9]==9, "c[9]==9"); +} + +void pass_param() +{ + int b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + __CPROVER_assert(b[0]==0, "b[0]==0"); + __CPROVER_assert(b[4]==4, "b[4]==4"); + __CPROVER_assert(b[8]==8, "b[8]==8"); + // TODO: This is marked as "unknown" when running analysis of pass_param. CORRECT? + // The theme here is that global array initialisation assertions are marked as "unknown". Why? + __CPROVER_assert(c[8]==8, "c[8]==8"); + + param_test(&a); +} \ No newline at end of file From 38d0b57558c835a1d1819d7ff5eec50d59f4b7f6 Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Tue, 22 Aug 2017 16:56:01 +0100 Subject: [PATCH 164/342] Added a struct c test file, and made some changes to the array testing code. --- .../main.c | 14 ++++++- .../main.c | 38 +++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c index 04c6dd7dcab..d2594e84c3e 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c @@ -7,7 +7,7 @@ void param_test(int array[]) array[1] = 5; // TODO: This is marked as "unknown" when running analysis of param_test and global_test. Doesn't seem correct // as array[1] is being assigned one line above? - __CPROVER_assert(a[1]==5, "a[1]==5"); + __CPROVER_assert(array[1]==5, "array[1]==5"); } void global_test() @@ -31,5 +31,15 @@ void pass_param() // The theme here is that global array initialisation assertions are marked as "unknown". Why? __CPROVER_assert(c[8]==8, "c[8]==8"); - param_test(&a); + param_test(a); + + __CPROVER_assert(a[1]==5, "a[1]==5"); + + __CPROVER_assert(b[0]==0, "b[0]==0"); + __CPROVER_assert(b[4]==4, "b[4]==4"); + __CPROVER_assert(b[8]==8, "b[8]==8"); + + __CPROVER_assert(b[1]==1, "b[1]==1"); + param_test(b); + __CPROVER_assert(b[1]==5, "b[1]==5"); } \ No newline at end of file diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c new file mode 100644 index 00000000000..83d72bd5087 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c @@ -0,0 +1,38 @@ +struct human { + int age; + float height; +}; + +struct human another_human = { 18, 1.73 }; + +void param_function(struct human a_human) +{ + __CPROVER_assert(a_human.age==24, "a_human.age==24"); + __CPROVER_assert(a_human.height==1.80, "a_human.height==1.80"); +} + +void param_function_mod(struct human *a_human) +{ + a_human->age = 10; + __CPROVER_assert(a_human->age==10, "a_human.age==10"); +} + + +void pass_param() +{ + struct human human_instance; + human_instance.age = 24; + human_instance.height = 1.80f; + __CPROVER_assert(human_instance.age==24, "human_instance.age==24"); + __CPROVER_assert(human_instance.height==1.80f, "human_instance.height==1.80"); + param_function_mod(&human_instance); + + __CPROVER_assert(human_instance.age==10, "human_instance.age==10"); + __CPROVER_assert(human_instance.height==1.80f, "human_instance.height==1.80"); +} + +void global_struct_test() +{ + __CPROVER_assert(another_human.age==18, "another_human.age==18"); + __CPROVER_assert(another_human.height==1.73f, "another_human.height==1.73"); +} \ No newline at end of file From 9f65c175b277eb04e04465075413d5d35da4065c Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Tue, 22 Aug 2017 17:08:47 +0100 Subject: [PATCH 165/342] Added some changes that thomas made on my machine to test arrays modified by functions. --- .../main.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c index d2594e84c3e..b6c80bcaef6 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c @@ -10,6 +10,14 @@ void param_test(int array[]) __CPROVER_assert(array[1]==5, "array[1]==5"); } +void param_test_val(int array[], int x) +{ + array[1] = x; + // TODO: This is marked as "unknown" when running analysis of param_test and global_test. Doesn't seem correct + // as array[1] is being assigned one line above? + //__CPROVER_assert(array[1]==5, "array[1]==5"); +} + void global_test() { a[2] = 6; @@ -31,15 +39,16 @@ void pass_param() // The theme here is that global array initialisation assertions are marked as "unknown". Why? __CPROVER_assert(c[8]==8, "c[8]==8"); - param_test(a); + param_test_val(b, 5); - __CPROVER_assert(a[1]==5, "a[1]==5"); + __CPROVER_assert(b[1]==5, "b[1]==5"); __CPROVER_assert(b[0]==0, "b[0]==0"); __CPROVER_assert(b[4]==4, "b[4]==4"); __CPROVER_assert(b[8]==8, "b[8]==8"); __CPROVER_assert(b[1]==1, "b[1]==1"); - param_test(b); + param_test_val(b, 6); __CPROVER_assert(b[1]==5, "b[1]==5"); + __CPROVER_assert(b[0]==0, "b[0]==0"); } \ No newline at end of file From 7c2efd98edceb43602dcda1743016b093977031f Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Wed, 23 Aug 2017 10:22:37 +0100 Subject: [PATCH 166/342] Added the test.desc files for tests of arrays and structs. --- .../main.c | 2 ++ .../test.desc | 19 +++++++++++++++++++ .../main.c | 1 + .../test.desc | 11 +++++++++++ 4 files changed, 33 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c index b6c80bcaef6..7dba7ad9273 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c @@ -50,5 +50,7 @@ void pass_param() __CPROVER_assert(b[1]==1, "b[1]==1"); param_test_val(b, 6); __CPROVER_assert(b[1]==5, "b[1]==5"); + __CPROVER_assert(b[1]==6, "b[1]==6"); __CPROVER_assert(b[0]==0, "b[0]==0"); + __CPROVER_assert(b[8]==8, "b[8]==8"); } \ No newline at end of file diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc new file mode 100644 index 00000000000..9fe1d7c581d --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc @@ -0,0 +1,19 @@ +CORE +main.c +--function pass_param --variable --pointers --arrays --structs --verify +^EXIT=0$ +^SIGNAL=0$ +^\[pass_param.assertion.1\] file main.c line 35 function pass_param, b\[0\]==0: Success$ +^\[pass_param.assertion.2\] file main.c line 36 function pass_param, b\[4\]==4: Success$ +^\[pass_param.assertion.3\] file main.c line 37 function pass_param, b\[8\]==8: Success$ +^\[pass_param.assertion.4\] file main.c line 40 function pass_param, c\[8\]==8: Unknown$ +^\[pass_param.assertion.5\] file main.c line 44 function pass_param, b\[1\]==5: Success$ +^\[pass_param.assertion.6\] file main.c line 46 function pass_param, b\[0\]==0: Success$ +^\[pass_param.assertion.7\] file main.c line 47 function pass_param, b\[4\]==4: Success$ +^\[pass_param.assertion.8\] file main.c line 48 function pass_param, b\[8\]==8: Success$ +^\[pass_param.assertion.9\] file main.c line 50 function pass_param, b\[1\]==1: Failure \(if reachable\)$ +^\[pass_param.assertion.10\] file main.c line 52 function pass_param, b\[1\]==5: Unknown$ +^\[pass_param.assertion.11\] file main.c line 53 function pass_param, b\[1\]==6: Unknown$ +^\[pass_param.assertion.12\] file main.c line 54 function pass_param, b\[0\]==0: Success$ +^\[pass_param.assertion.13\] file main.c line 55 function pass_param, b\[8\]==8: Success$ +-- \ No newline at end of file diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c index 83d72bd5087..11a58edc460 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c @@ -28,6 +28,7 @@ void pass_param() param_function_mod(&human_instance); __CPROVER_assert(human_instance.age==10, "human_instance.age==10"); + __CPROVER_assert(human_instance.age==24, "human_instance.age==24"); __CPROVER_assert(human_instance.height==1.80f, "human_instance.height==1.80"); } diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc new file mode 100644 index 00000000000..527548620f6 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc @@ -0,0 +1,11 @@ +CORE +main.c +--function pass_param --variable --pointers --arrays --structs --verify +^EXIT=0$ +^SIGNAL=0$ +^\[pass_param.assertion.1\] file main.c line 26 function pass_param, human_instance.age==24: Success$ +^\[pass_param.assertion.2\] file main.c line 27 function pass_param, human_instance.height==1.80: Success$ +^\[pass_param.assertion.3\] file main.c line 30 function pass_param, human_instance.age==10: Success$ +^\[pass_param.assertion.4\] file main.c line 31 function pass_param, human_instance.age==24: Failure \(if reachable\)$ +^\[pass_param.assertion.5\] file main.c line 32 function pass_param, human_instance.height==1.80: Success$ +-- \ No newline at end of file From 4dd8711a900e1ada8bd5d88234225b1402c992f3 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 23 Aug 2017 10:26:52 +0100 Subject: [PATCH 167/342] Fixing comment --- .../variable-sensitivity/variable_sensitivity_domain.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 24a4931f4e1..1a3daa7d188 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -137,7 +137,7 @@ void variable_sensitivity_domaint::transform( for(const auto ¶m : type.parameters()) { - // Bottom the arguments to the function + // Top the arguments to the function abstract_state.assign( symbol_exprt(param.get_identifier(), param.type()), abstract_state.abstract_object_factory(param.type(), ns, true, false), @@ -541,4 +541,4 @@ void variable_sensitivity_domaint::restore_domain(std::vector modi auto value = abstract_state.eval(symbol, ns); target.abstract_state.assign(symbol, value, ns); } -} \ No newline at end of file +} From 125b44ac719d6771db258d0813ca4ce608b02af5 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 23 Aug 2017 10:28:54 +0100 Subject: [PATCH 168/342] Correctly escaping braces --- .../test.desc | 38 ++++++------- .../test.desc | 56 +++++++++---------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc index c90e10cd875..5f11971ef98 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc @@ -19,23 +19,23 @@ main#return_value \(\) -> TOP @ \[1\] do_arrays::1::bool_ \(\) -> TOP @ \[16\] do_arrays::1::bool_1 \(\) -> TOP @ \[17\] do_arrays::1::bool_2 \(\) -> TOP @ \[18\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000011110 @ \[22\]\n\[1\] = 00000000000000000000000000010100 @ \[21\]\n} @ \[22\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000011110 @ \[22\]\n\[1\] = 00000000000000000000000000101000 @ \[23\]\n} @ \[23\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000011110 @ \[22\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n} @ \[24\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000011110 @ \[25\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n} @ \[25\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000000101 @ \[26\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n} @ \[26\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n} @ \[27\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[28\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[28\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000010100 @ \[30\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[30\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[28\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000010100 @ \[30\, 32\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[30\, 32\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000000000 @ \[34\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[34\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000000011 @ \[36\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[36\] -do_arrays::1::x \(\) -> {\[0\] = TOP @ \[36\, 38\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[36\, 38\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000000000 @ \[34\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[34\] -do_arrays::1::x \(\) -> {\[0\] = TOP @ \[36\, 38\, 41\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[36\, 38\, 41\] -do_arrays::1::x \(\) -> {\[0\] = TOP @ \[36\, 38\, 41\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n} @ \[36\, 38\, 41\] -do_arrays::1::x \(\) -> {\[0\] = TOP @ \[36\, 38\, 41\]\n\[1\] = 00000000000000000000000000001010 @ \[43\]\n} @ \[43\] -do_arrays::1::x \(\) -> {\[0\] = 00000000000000000000000000010100 @ \[44\]\n\[1\] = 00000000000000000000000000001010 @ \[43\]\n} @ \[44\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000011110 @ \[22\]\n\[1\] = 00000000000000000000000000010100 @ \[21\]\n\} @ \[22\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000011110 @ \[22\]\n\[1\] = 00000000000000000000000000101000 @ \[23\]\n\} @ \[23\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000011110 @ \[22\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n\} @ \[24\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000011110 @ \[25\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n\} @ \[25\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000000101 @ \[26\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n\} @ \[26\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n\} @ \[27\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[28\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[28\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000010100 @ \[30\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[30\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[28\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000010100 @ \[30\, 32\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[30\, 32\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000000000 @ \[34\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[34\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000000011 @ \[36\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[36\] +do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[36\, 38\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[36\, 38\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000000000 @ \[34\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[34\] +do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[36\, 38\, 41\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[36\, 38\, 41\] +do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[36\, 38\, 41\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[36\, 38\, 41\] +do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[36\, 38\, 41\]\n\[1\] = 00000000000000000000000000001010 @ \[43\]\n\} @ \[43\] +do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000010100 @ \[44\]\n\[1\] = 00000000000000000000000000001010 @ \[43\]\n\} @ \[44\] -- diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc index 234218b5cb6..3584c63c1d4 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc @@ -19,32 +19,32 @@ main#return_value \(\) -> TOP @ \[1\] do_structs::1::bool_ \(\) -> TOP @ \[16\] do_structs::1::bool_1 \(\) -> TOP @ \[17\] do_structs::1::bool_2 \(\) -> TOP @ \[18\] -do_structs::1::st \(\) -> {} @ \[19\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000001010 @ \[20\]} @ \[20\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000001010 @ \[20\]\, .y=00000000000000000000000000010100 @ \[21\]} @ \[21\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000011110 @ \[22\]\, .y=00000000000000000000000000010100 @ \[21\]} @ \[22\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000011110 @ \[22\]\, .y=00000000000000000000000000101000 @ \[23\]} @ \[23\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000011110 @ \[22\]\, .y=00000000000000000000000000011110 @ \[24\]} @ \[24\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000011110 @ \[25\]\, .y=00000000000000000000000000011110 @ \[24\]} @ \[25\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000000101 @ \[26\]\, .y=00000000000000000000000000011110 @ \[24\]} @ \[26\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000011110 @ \[24\]} @ \[27\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[28\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[28\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000010100 @ \[30\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[30\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[28\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000010100 @ \[30\, 32\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[30\, 32\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000010100 @ \[30\, 32\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[30\, 32\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000000000 @ \[34\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[34\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000000000 @ \[34\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[34\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000000011 @ \[36\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[36\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000000011 @ \[36\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[36\] -do_structs::1::st \(\) -> {.x=TOP @ \[36\, 38\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[36\, 38\] -do_structs::1::st \(\) -> {.x=TOP @ \[36\, 38\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[36\, 38\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000000000 @ \[34\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[34\] -do_structs::1::st \(\) -> {.x=TOP @ \[36\, 38\, 41\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[36\, 38\, 41\] -do_structs::1::st \(\) -> {.x=TOP @ \[36\, 38\, 41\]\, .y=00000000000000000000000000001010 @ \[28\]} @ \[36\, 38\, 41\] -do_structs::1::st \(\) -> {.x=TOP @ \[36\, 38\, 41\]\, .y=00000000000000000000000000001010 @ \[43\]} @ \[43\] -do_structs::1::st \(\) -> {.x=00000000000000000000000000010100 @ \[44\]\, .y=00000000000000000000000000001010 @ \[43\]} @ \[44\] -do_structs::1::new_age \(\) -> {} @ \[45\] -do_structs::1::new_age \(\) -> {.x=00000000000000000000000000010100 @ \[46\]\, .y=00000000000000000000000000001010 @ \[46\]} @ \[46\] +do_structs::1::st \(\) -> \{ \} @ \[19\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000001010 @ \[20\]\} @ \[20\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000001010 @ \[20\]\, .y=00000000000000000000000000010100 @ \[21\]\} @ \[21\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000011110 @ \[22\]\, .y=00000000000000000000000000010100 @ \[21\]\} @ \[22\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000011110 @ \[22\]\, .y=00000000000000000000000000101000 @ \[23\]\} @ \[23\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000011110 @ \[22\]\, .y=00000000000000000000000000011110 @ \[24\]\} @ \[24\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000011110 @ \[25\]\, .y=00000000000000000000000000011110 @ \[24\]\} @ \[25\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000000101 @ \[26\]\, .y=00000000000000000000000000011110 @ \[24\]\} @ \[26\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000011110 @ \[24\]\} @ \[27\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[28\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[28\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000010100 @ \[30\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[30\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[28\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000010100 @ \[30\, 32\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[30\, 32\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000010100 @ \[30\, 32\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[30\, 32\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000000000 @ \[34\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[34\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000000000 @ \[34\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[34\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000000011 @ \[36\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[36\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000000011 @ \[36\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[36\] +do_structs::1::st \(\) -> \{.x=TOP @ \[36\, 38\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[36\, 38\] +do_structs::1::st \(\) -> \{.x=TOP @ \[36\, 38\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[36\, 38\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000000000 @ \[34\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[34\] +do_structs::1::st \(\) -> \{.x=TOP @ \[36\, 38\, 41\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[36\, 38\, 41\] +do_structs::1::st \(\) -> \{.x=TOP @ \[36\, 38\, 41\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[36\, 38\, 41\] +do_structs::1::st \(\) -> \{.x=TOP @ \[36\, 38\, 41\]\, .y=00000000000000000000000000001010 @ \[43\]\} @ \[43\] +do_structs::1::st \(\) -> \{.x=00000000000000000000000000010100 @ \[44\]\, .y=00000000000000000000000000001010 @ \[43\]\} @ \[44\] +do_structs::1::new_age \(\) -> \{\} @ \[45\] +do_structs::1::new_age \(\) -> \{.x=00000000000000000000000000010100 @ \[46\]\, .y=00000000000000000000000000001010 @ \[46\]\} @ \[46\] -- From ac65156f8f6eb099dec35618c51100247623781c Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 23 Aug 2017 11:19:23 +0100 Subject: [PATCH 169/342] Delete incorrect comment and fixing whitespace bug --- .../variable-sensitivity/constant_pointer_abstract_object.cpp | 2 +- .../variable-sensitivity/full_struct_abstract_object.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 764638fd2db..7e685b1123e 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -346,7 +346,7 @@ sharing_ptrt environment.eval(value, ns); abstract_object_pointert modified_value= environment.write(pointed_value, new_value, stack, ns, merging_write); - environment.assign(value, modified_value, ns); + environment.assign(value, modified_value, ns); // but the pointer itself does not change! } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 4587d44e6c9..6b07db44a6b 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -182,7 +182,6 @@ sharing_ptrt member_expr.compound().type(), false, true)); } - // we only handle one level currently if(!stack.empty()) { internal_sharing_ptrt copy( From 24b3c7ab6ede7946da5b614f8b83aba4e4e13768 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 23 Aug 2017 11:20:13 +0100 Subject: [PATCH 170/342] Update the last written location for structs When updating a component in a struct container, we must update the last written location for the struct container itself. --- .../full_struct_abstract_object.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 6b07db44a6b..64ace377e9d 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -182,11 +182,13 @@ sharing_ptrt member_expr.compound().type(), false, true)); } + internal_sharing_ptrt copy( + new full_struct_abstract_objectt(*this)); + + copy->set_last_written_locations(value->get_last_written_locations()); + if(!stack.empty()) { - 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()) @@ -208,8 +210,6 @@ sharing_ptrt } else { - internal_sharing_ptrt copy( - new full_struct_abstract_objectt(*this)); #ifdef DEBUG std::cout << "Setting component" << std::endl; @@ -244,7 +244,6 @@ sharing_ptrt else { copy->map[c]=value; - copy->top=false; assert(!copy->is_bottom()); } From 3bce160bca2946e3574ae3d7da6a66a938e8121e Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 23 Aug 2017 11:34:19 +0100 Subject: [PATCH 171/342] Fixed typo introduced in test --- .../sensitivity-last-written-locations-structs/test.desc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc index 3584c63c1d4..043a899b5f3 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc @@ -19,7 +19,7 @@ main#return_value \(\) -> TOP @ \[1\] do_structs::1::bool_ \(\) -> TOP @ \[16\] do_structs::1::bool_1 \(\) -> TOP @ \[17\] do_structs::1::bool_2 \(\) -> TOP @ \[18\] -do_structs::1::st \(\) -> \{ \} @ \[19\] +do_structs::1::st \(\) -> \{\} @ \[19\] do_structs::1::st \(\) -> \{.x=00000000000000000000000000001010 @ \[20\]\} @ \[20\] do_structs::1::st \(\) -> \{.x=00000000000000000000000000001010 @ \[20\]\, .y=00000000000000000000000000010100 @ \[21\]\} @ \[21\] do_structs::1::st \(\) -> \{.x=00000000000000000000000000011110 @ \[22\]\, .y=00000000000000000000000000010100 @ \[21\]\} @ \[22\] From 14169e0bc03787cf4aafeb46f0b16cfbc9312f20 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 23 Aug 2017 13:11:24 +0100 Subject: [PATCH 172/342] Add any elements that are only in the second map since this is modified --- .../variable-sensitivity/abstract_enviroment.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index f5b73f5ffc0..a898c36e754 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -852,5 +852,14 @@ std::vector abstract_environmentt::modified_symbols( } } } + + for(const auto &entry : second.map) + { + const auto &second_entry = first.map.find(entry.first); + if (second_entry==first.map.end()) + { + symbols_diff.push_back(entry.first); + } + } return symbols_diff; } From de8b6559cc1f904e7f4f7c50fdfd802532ca643e Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 23 Aug 2017 13:18:17 +0100 Subject: [PATCH 173/342] Updated array test to test exactly what we want --- .../main.c | 49 ++++--------------- .../test.desc | 18 ++----- 2 files changed, 15 insertions(+), 52 deletions(-) diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c index 7dba7ad9273..553697b1b07 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c @@ -1,56 +1,27 @@ -int a[10]; - -int c[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - -void param_test(int array[]) -{ - array[1] = 5; - // TODO: This is marked as "unknown" when running analysis of param_test and global_test. Doesn't seem correct - // as array[1] is being assigned one line above? - __CPROVER_assert(array[1]==5, "array[1]==5"); -} - void param_test_val(int array[], int x) { array[1] = x; - // TODO: This is marked as "unknown" when running analysis of param_test and global_test. Doesn't seem correct - // as array[1] is being assigned one line above? - //__CPROVER_assert(array[1]==5, "array[1]==5"); -} - -void global_test() -{ - a[2] = 6; - __CPROVER_assert(a[2]==6, "a[2]==6"); - c[8] = 15; - __CPROVER_assert(c[8]==15, "c[8]==15"); - // TODO: This is marked as "unknown" when running analysis of global_test. CORRECT? - __CPROVER_assert(c[9]==9, "c[9]==9"); } void pass_param() { int b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - - __CPROVER_assert(b[0]==0, "b[0]==0"); - __CPROVER_assert(b[4]==4, "b[4]==4"); - __CPROVER_assert(b[8]==8, "b[8]==8"); - // TODO: This is marked as "unknown" when running analysis of pass_param. CORRECT? - // The theme here is that global array initialisation assertions are marked as "unknown". Why? - __CPROVER_assert(c[8]==8, "c[8]==8"); - - param_test_val(b, 5); - __CPROVER_assert(b[1]==5, "b[1]==5"); + param_test_val(b, 5); + // This assertion should be true since b[0] is unmodified __CPROVER_assert(b[0]==0, "b[0]==0"); - __CPROVER_assert(b[4]==4, "b[4]==4"); - __CPROVER_assert(b[8]==8, "b[8]==8"); - __CPROVER_assert(b[1]==1, "b[1]==1"); + // This assertion should be true since b[1] can only have one value + __CPROVER_assert(b[1]==5, "b[1]==5"); + param_test_val(b, 6); + + // Both these assertions shoul be unknown since the domain for + // param_test_val, x is TOP so we don't know what is written __CPROVER_assert(b[1]==5, "b[1]==5"); __CPROVER_assert(b[1]==6, "b[1]==6"); + + // b[0] is still not modified so this assertion should still be true __CPROVER_assert(b[0]==0, "b[0]==0"); - __CPROVER_assert(b[8]==8, "b[8]==8"); } \ No newline at end of file diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc index 9fe1d7c581d..9b3c9311d75 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc @@ -3,17 +3,9 @@ main.c --function pass_param --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[pass_param.assertion.1\] file main.c line 35 function pass_param, b\[0\]==0: Success$ -^\[pass_param.assertion.2\] file main.c line 36 function pass_param, b\[4\]==4: Success$ -^\[pass_param.assertion.3\] file main.c line 37 function pass_param, b\[8\]==8: Success$ -^\[pass_param.assertion.4\] file main.c line 40 function pass_param, c\[8\]==8: Unknown$ -^\[pass_param.assertion.5\] file main.c line 44 function pass_param, b\[1\]==5: Success$ -^\[pass_param.assertion.6\] file main.c line 46 function pass_param, b\[0\]==0: Success$ -^\[pass_param.assertion.7\] file main.c line 47 function pass_param, b\[4\]==4: Success$ -^\[pass_param.assertion.8\] file main.c line 48 function pass_param, b\[8\]==8: Success$ -^\[pass_param.assertion.9\] file main.c line 50 function pass_param, b\[1\]==1: Failure \(if reachable\)$ -^\[pass_param.assertion.10\] file main.c line 52 function pass_param, b\[1\]==5: Unknown$ -^\[pass_param.assertion.11\] file main.c line 53 function pass_param, b\[1\]==6: Unknown$ -^\[pass_param.assertion.12\] file main.c line 54 function pass_param, b\[0\]==0: Success$ -^\[pass_param.assertion.13\] file main.c line 55 function pass_param, b\[8\]==8: Success$ +\[pass_param\.assertion\.1\] .* b\[0\]==0: Success +\[pass_param\.assertion\.2\] .* b\[1\]==5: Success +\[pass_param\.assertion\.3\] .* b\[1\]==5: Unknown +\[pass_param\.assertion\.4\] .* b\[1\]==6: Unknown +\[pass_param\.assertion\.5\] .* b\[0\]==0: Success -- \ No newline at end of file From f0543668913bb75fd7917b2db85451906f5ac26c Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Wed, 23 Aug 2017 13:23:59 +0100 Subject: [PATCH 174/342] Fixed the struct test.desc --- .../main.c | 12 ++++++++---- .../test.desc | 13 ++++++++----- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c index 11a58edc460..5dffda89aa4 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c @@ -11,10 +11,9 @@ void param_function(struct human a_human) __CPROVER_assert(a_human.height==1.80, "a_human.height==1.80"); } -void param_function_mod(struct human *a_human) +void param_function_val(struct human *a_human, int val) { - a_human->age = 10; - __CPROVER_assert(a_human->age==10, "a_human.age==10"); + a_human->age = val; } @@ -25,11 +24,16 @@ void pass_param() human_instance.height = 1.80f; __CPROVER_assert(human_instance.age==24, "human_instance.age==24"); __CPROVER_assert(human_instance.height==1.80f, "human_instance.height==1.80"); - param_function_mod(&human_instance); + param_function_val(&human_instance, 10); __CPROVER_assert(human_instance.age==10, "human_instance.age==10"); __CPROVER_assert(human_instance.age==24, "human_instance.age==24"); __CPROVER_assert(human_instance.height==1.80f, "human_instance.height==1.80"); + + param_function_val(&human_instance, 32); + __CPROVER_assert(human_instance.age==32, "human_instance.age==32"); + __CPROVER_assert(human_instance.age==10, "human_instance.age==10"); + __CPROVER_assert(human_instance.height==1.80f, "human_instance.height==1.80"); } void global_struct_test() diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc index 527548620f6..ab3a2603306 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc @@ -3,9 +3,12 @@ main.c --function pass_param --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[pass_param.assertion.1\] file main.c line 26 function pass_param, human_instance.age==24: Success$ -^\[pass_param.assertion.2\] file main.c line 27 function pass_param, human_instance.height==1.80: Success$ -^\[pass_param.assertion.3\] file main.c line 30 function pass_param, human_instance.age==10: Success$ -^\[pass_param.assertion.4\] file main.c line 31 function pass_param, human_instance.age==24: Failure \(if reachable\)$ -^\[pass_param.assertion.5\] file main.c line 32 function pass_param, human_instance.height==1.80: Success$ +^\[pass_param.assertion.1\] .* human_instance.age==24: Success$ +^\[pass_param.assertion.2\] .* human_instance.height==1.80: Success$ +^\[pass_param.assertion.3\] .* human_instance.age==10: Success$ +^\[pass_param.assertion.4\] .* human_instance.age==24: Failure \(if reachable\)$ +^\[pass_param.assertion.5\] .* human_instance.height==1.80: Success$ +^\[pass_param.assertion.6\] .* human_instance.age==32: Unknown$ +^\[pass_param.assertion.7\] .* human_instance.age==10: Unknown$ +^\[pass_param.assertion.8\] .* human_instance.height==1.80: Success$ -- \ No newline at end of file From 36d91d8371b23aa09e0aafd323200ec83edd1a13 Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 23 Aug 2017 14:58:21 +0100 Subject: [PATCH 175/342] Three way merge initial checkin --- .../variable_sensitivity_domain.cpp | 33 +++++++++++++++---- .../variable_sensitivity_domain.h | 14 ++++++-- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 1a3daa7d188..debe73d6fb9 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -529,16 +529,37 @@ bool variable_sensitivity_domaint::ignore_function_call_transform( }; return ignored_internal_function.find(function_id)!= - ignored_internal_function.cend(); + ignored_internal_function.cend(); } -void variable_sensitivity_domaint::restore_domain(std::vector modified_symbols, - variable_sensitivity_domaint &target, - const namespacet &ns) const +void variable_sensitivity_domaint::merge_three_way_function_return( + const ai_domain_baset &function_start, + const ai_domain_baset &function_end, + const namespacet &ns) +{ +// const variable_sensitivity_domaint &cast_function_call_site= +// static_cast(function_call_site); + + const variable_sensitivity_domaint &cast_function_start= + static_cast(function_start); + + const variable_sensitivity_domaint &cast_function_end= + static_cast(function_end); + + const std::vector &modified_symbols= + cast_function_start.get_modified_symbols(cast_function_end); + + apply_domain(modified_symbols, cast_function_end, ns); +} + +void variable_sensitivity_domaint::apply_domain( + std::vector modified_symbols, + const variable_sensitivity_domaint &source, + const namespacet &ns) { for (const auto &symbol : modified_symbols) { - auto value = abstract_state.eval(symbol, ns); - target.abstract_state.assign(symbol, value, ns); + auto value = source.abstract_state.eval(symbol, ns); + this->abstract_state.assign(symbol, value, ns); } } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index b321f5d8692..2d4ee273185 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -99,6 +99,11 @@ class variable_sensitivity_domaint:public ai_domain_baset locationt from, locationt to); + void merge_three_way_function_return( + const ai_domain_baset &function_start, + const ai_domain_baset &function_end, + const namespacet &ns) override; + bool ai_simplify( exprt &condition, const namespacet &ns) const override; @@ -106,13 +111,16 @@ class variable_sensitivity_domaint:public ai_domain_baset bool is_bottom() const override; bool is_top() const override; - virtual std::vector get_modified_symbols(const variable_sensitivity_domaint &other) const + std::vector get_modified_symbols(const variable_sensitivity_domaint &other) const { return abstract_environmentt::modified_symbols(abstract_state, other.abstract_state); } - virtual void restore_domain(std::vector modified_symbols, - variable_sensitivity_domaint &target, const namespacet &ns) const; + + virtual void apply_domain( + std::vector modified_symbols, + const variable_sensitivity_domaint &target, + const namespacet &ns); private: void transform_function_call( From 078bcb972d2fb5f06f27e97b4b4da6943d48ba7d Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Wed, 23 Aug 2017 15:44:39 +0100 Subject: [PATCH 176/342] Added tests for goto after function. --- .../main.c | 26 +++++++++++++++++++ .../test.desc | 9 +++++++ 2 files changed, 35 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/main.c new file mode 100644 index 00000000000..da3e308c69f --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/main.c @@ -0,0 +1,26 @@ +void param_function(int *old_val, int new_val) +{ + *old_val = new_val; +} + +void param_function_extra(int *old_val, int new_val) +{ + *old_val = new_val; +} + +void test_param_function(int nondet) +{ + int a = 5; + int b; + __CPROVER_assert(a==5, "a==5"); + if (nondet) { + a = 6; + b = 7; + goto whatever; + } + param_function(&a, 10); + param_function_extra(&b, 7); +whatever: + __CPROVER_assert(a==10, "a==10"); + __CPROVER_assert(b==7, "b==7"); +} \ No newline at end of file diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc new file mode 100644 index 00000000000..a6fe7cfe1e8 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc @@ -0,0 +1,9 @@ +CORE +main.c +--function test_param_function --variable --pointers --arrays --structs --verify +^EXIT=0$ +^SIGNAL=0$ +[test_param_function.assertion.1] .* a==5: Success +[test_param_function.assertion.2] .* a==10: Unknown +[test_param_function.assertion.3] .* b==7: Success +-- \ No newline at end of file From dc7d9f0b5938c6273a8831ab101ce209beda5100 Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Wed, 23 Aug 2017 15:45:00 +0100 Subject: [PATCH 177/342] Added tests for the non-terminating function case. --- .../main.c | 32 +++++++++++++++++++ .../test.desc | 11 +++++++ 2 files changed, 43 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/main.c new file mode 100644 index 00000000000..b2c9858f8f2 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/main.c @@ -0,0 +1,32 @@ +int non_terminating(int *a, int val) +{ + while (1) + { + a = val; + } + return a; +} + +int non_terminating_extra(int *a, int val) +{ + while (1) + { + a = val; + } + return a; +} + +void test_non_terminating() +{ + int one_val = 5; + int second_val = 6; + __CPROVER_assert(one_val==5, "one_val==5"); + __CPROVER_assert(second_val==6, "second_val==6"); + + non_terminating(&one_val, 10); + __CPROVER_assert(one_val==10, "one_val==10"); + non_terminating_extra(&second_val, 12); + __CPROVER_assert(second_val==12, "second_val==12"); + non_terminating_extra(&second_val, 13); + __CPROVER_assert(second_val==13, "second_val==13"); +} \ No newline at end of file diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/test.desc new file mode 100644 index 00000000000..e62079ecc21 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/test.desc @@ -0,0 +1,11 @@ +CORE +main.c +--function test_non_terminating --variable --pointers --arrays --structs --verify +^EXIT=0$ +^SIGNAL=0$ +[test_non_terminating.assertion.1] .* one_val==5: Success +[test_non_terminating.assertion.2] .* second_val==6: Success +[test_non_terminating.assertion.3] .* one_val==10: Success \(unreachable\) +[test_non_terminating.assertion.4] .* second_val==12: Success \(unreachable\) +[test_non_terminating.assertion.5] .* second_val==13: Success \(unreachable\) +-- \ No newline at end of file From 4a2f147900705cf0a6dbac3aaa7d441aed1905aa Mon Sep 17 00:00:00 2001 From: thk123 Date: Wed, 23 Aug 2017 18:12:42 +0100 Subject: [PATCH 178/342] Reworked three way merge that works when enabled and not --- .../abstract_enviroment.cpp | 2 + .../variable_sensitivity_domain.cpp | 63 ++++++++++++++----- .../variable_sensitivity_domain.h | 20 +++--- 3 files changed, 60 insertions(+), 25 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index a898c36e754..a2613359a59 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -833,6 +833,7 @@ std::vector abstract_environmentt::modified_symbols( bool all_matched=intersection.size()==a.size() && intersection.size()==b.size(); +#if 0 std::cout << entry.first.get_identifier() << ": {"; for(const auto &entry:lhs_location) { @@ -845,6 +846,7 @@ std::vector abstract_environmentt::modified_symbols( std::cout << entry->location_number << ", "; } std::cout << " }" << std::endl; +#endif if (!all_matched) { diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index debe73d6fb9..1d96151b972 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -370,6 +370,17 @@ bool variable_sensitivity_domaint::is_top() const return abstract_state.is_top(); } +/// Get symbols that have been modified since this domain and other +/// \param other: The domain that things may have been modified in +/// \return A list of symbols whose write location is different +std::vector + variable_sensitivity_domaint::get_modified_symbols( + const variable_sensitivity_domaint &other) const +{ + return abstract_environmentt::modified_symbols( + abstract_state, other.abstract_state); +} + /*******************************************************************\ Function: variable_sensitivity_domaint::transform_function_call @@ -532,34 +543,58 @@ bool variable_sensitivity_domaint::ignore_function_call_transform( ignored_internal_function.cend(); } +/// Perform a context aware merge of the changes that have been applied +/// between function_start and the current state. Anything that has not been +/// modified will be taken from the \p function_call domain. +/// \param function_call: The local of the merge - values from here will be +/// taken if they have not been modified +/// \param function_start: THe base of the merge - changes that have been made +/// between here and this will be retained. +/// \param ns: The global namespace void variable_sensitivity_domaint::merge_three_way_function_return( + const ai_domain_baset &function_call, const ai_domain_baset &function_start, const ai_domain_baset &function_end, const namespacet &ns) { -// const variable_sensitivity_domaint &cast_function_call_site= -// static_cast(function_call_site); + // TODO(tkiley): flag to turn of the context aware merge + if(true) + { + const variable_sensitivity_domaint &cast_function_call= + static_cast(function_call); - const variable_sensitivity_domaint &cast_function_start= - static_cast(function_start); + const variable_sensitivity_domaint &cast_function_start= + static_cast(function_start); - const variable_sensitivity_domaint &cast_function_end= - static_cast(function_end); + const variable_sensitivity_domaint &cast_function_end= + static_cast(function_end); - const std::vector &modified_symbols= - cast_function_start.get_modified_symbols(cast_function_end); + const std::vector &modified_symbols= + cast_function_start.get_modified_symbols(cast_function_end); - apply_domain(modified_symbols, cast_function_end, ns); + abstract_state=cast_function_call.abstract_state; + apply_domain(modified_symbols, cast_function_end, ns); + } + else + { + ai_domain_baset::merge_three_way_function_return( + function_call, function_start, function_end, ns); + } } +/// Given a domain and some symbols, apply those symbols values +/// to the current domain +/// \param modified_symbols: The symbols to write +/// \param source: The domain to take the values from +/// \param ns: The global namespace void variable_sensitivity_domaint::apply_domain( std::vector modified_symbols, const variable_sensitivity_domaint &source, const namespacet &ns) { - for (const auto &symbol : modified_symbols) - { - auto value = source.abstract_state.eval(symbol, ns); - this->abstract_state.assign(symbol, value, ns); - } + for (const auto &symbol : modified_symbols) + { + abstract_object_pointert value=source.abstract_state.eval(symbol, ns); + abstract_state.assign(symbol, value, ns); + } } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 2d4ee273185..e7d0983d600 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -100,6 +100,7 @@ class variable_sensitivity_domaint:public ai_domain_baset locationt to); void merge_three_way_function_return( + const ai_domain_baset &function_call, const ai_domain_baset &function_start, const ai_domain_baset &function_end, const namespacet &ns) override; @@ -111,17 +112,6 @@ class variable_sensitivity_domaint:public ai_domain_baset bool is_bottom() const override; bool is_top() const override; - std::vector get_modified_symbols(const variable_sensitivity_domaint &other) const - { - return abstract_environmentt::modified_symbols(abstract_state, other.abstract_state); - } - - - virtual void apply_domain( - std::vector modified_symbols, - const variable_sensitivity_domaint &target, - const namespacet &ns); - private: void transform_function_call( locationt from, @@ -131,6 +121,14 @@ class variable_sensitivity_domaint:public ai_domain_baset bool ignore_function_call_transform(const irep_idt &function_id) const; + std::vector get_modified_symbols( + const variable_sensitivity_domaint &other) const; + + void apply_domain( + std::vector modified_symbols, + const variable_sensitivity_domaint &target, + const namespacet &ns); + abstract_environmentt abstract_state; }; From 44c3936b6d20a320187413deebc97d3007179653 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 24 Aug 2017 15:41:36 +0100 Subject: [PATCH 179/342] Tidied up the changes introduced by context aware merging --- .../abstract_enviroment.cpp | 48 ++++++------------- .../variable_sensitivity_domain.cpp | 9 ---- 2 files changed, 14 insertions(+), 43 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index a2613359a59..c7bb4bb875c 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -771,6 +771,7 @@ Function: abstract_environmentt::environment_diff std::vector abstract_environmentt::modified_symbols( const abstract_environmentt &first, const abstract_environmentt &second) { + // Find all symbols who have different write locations in each map std::vector symbols_diff; for (const auto &entry : first.map) { @@ -782,19 +783,10 @@ std::vector abstract_environmentt::modified_symbols( // in the other // Since a set can assume at most one match -#if 0 - const auto location_matcher= - [&]( - goto_programt::const_targett instruction, - goto_programt::const_targett other_instruction) - { - return other_instruction->location_numberlocation_number; - }; -#endif - - - const abstract_objectt::locationst &a=entry.second->get_last_written_locations(); - const abstract_objectt::locationst &b=second_entry->second->get_last_written_locations(); + const abstract_objectt::locationst &first_write_locations= + entry.second->get_last_written_locations(); + const abstract_objectt::locationst &second_write_locations= + second_entry->second->get_last_written_locations(); class location_ordert { @@ -803,21 +795,23 @@ std::vector abstract_environmentt::modified_symbols( goto_programt::const_targett instruction, goto_programt::const_targett other_instruction) { - return instruction->location_number>other_instruction->location_number; + return instruction->location_number> + other_instruction->location_number; } }; - typedef std::set sorted_locationst; + typedef std::set + sorted_locationst; sorted_locationst lhs_location; - for(const auto &entry:a) + for(const auto &entry:first_write_locations) { lhs_location.insert(entry); } sorted_locationst rhs_location; - for(const auto &entry:b) + for(const auto &entry:second_write_locations) { rhs_location.insert(entry); } @@ -830,23 +824,8 @@ std::vector abstract_environmentt::modified_symbols( rhs_location.cend(), std::inserter(intersection, intersection.end()), location_ordert()); - bool all_matched=intersection.size()==a.size() && - intersection.size()==b.size(); - -#if 0 - std::cout << entry.first.get_identifier() << ": {"; - for(const auto &entry:lhs_location) - { - std::cout << entry->location_number << ", "; - } - - std::cout << " } vs { "; - for(const auto &entry:rhs_location) - { - std::cout << entry->location_number << ", "; - } - std::cout << " }" << std::endl; -#endif + bool all_matched=intersection.size()==first_write_locations.size() && + intersection.size()==second_write_locations.size(); if (!all_matched) { @@ -855,6 +834,7 @@ std::vector abstract_environmentt::modified_symbols( } } + // Add any symbols that are only in the second map for(const auto &entry : second.map) { const auto &second_entry = first.map.find(entry.first); diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 1d96151b972..1a4041052e5 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -17,8 +17,6 @@ Date: April 2016 #include "variable_sensitivity_domain.h" #include -#define DEBUG - #ifdef DEBUG #include #endif @@ -183,8 +181,6 @@ void variable_sensitivity_domaint::transform( throw "unrecognised instruction type"; } - output(std::cout, ai, ns); - assert(abstract_state.verify()); } @@ -282,11 +278,6 @@ bool variable_sensitivity_domaint::merge( << to->location_number << std::endl; #endif - if(from->location_number==43) - { - - } - // Use the abstract_environment merge bool any_changes=abstract_state.merge(b.abstract_state); From c9f3816c96a570cf7ba69eedc070e29e640eb2ea Mon Sep 17 00:00:00 2001 From: martin Date: Wed, 6 Dec 2017 11:55:20 +0000 Subject: [PATCH 180/342] Tweak to cope with missing utility function. --- src/analyses/variable-sensitivity/write_stack.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/write_stack.cpp b/src/analyses/variable-sensitivity/write_stack.cpp index 30ec0e07dc8..1d4b69b1917 100644 --- a/src/analyses/variable-sensitivity/write_stack.cpp +++ b/src/analyses/variable-sensitivity/write_stack.cpp @@ -14,6 +14,7 @@ #include +#include #include #include @@ -41,7 +42,7 @@ write_stackt::write_stackt( construct_stack_to_pointer( address_of_exprt( index_exprt( - expr, constant_exprt::integer_constant(0))), environment, ns); + expr, from_integer(0, integer_typet()))), environment, ns); } else { From 4ca731b09e852c2369b341084a1b4587e5e9ce42 Mon Sep 17 00:00:00 2001 From: martin Date: Wed, 6 Dec 2017 12:36:43 +0000 Subject: [PATCH 181/342] Fix up the last written location sensitivity tests. --- .../sensitivity_dependency_arrays.c | 10 +++++----- .../test.desc | 3 +-- .../sensitivity_dependency_pointers.c | 10 +++++----- .../test.desc | 3 +-- .../sensitivity_dependency_structs.c | 11 ++++++----- .../test.desc | 3 +-- .../sensitivity_dependency_variables.c | 10 +++++----- .../test.desc | 3 +-- 8 files changed, 25 insertions(+), 28 deletions(-) diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/sensitivity_dependency_arrays.c b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/sensitivity_dependency_arrays.c index 55458b1aec2..6fa4d476ef4 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/sensitivity_dependency_arrays.c +++ b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/sensitivity_dependency_arrays.c @@ -1,8 +1,3 @@ -int main() -{ - do_arrays(); -} - void do_arrays() { int bool_; @@ -48,3 +43,8 @@ void do_arrays() x[1]=10; x[0]=20; } + +int main() +{ + do_arrays(); +} diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc index 5f11971ef98..f753d144dae 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_dependency_arrays.c ---variable --arrays --pointers --structs +--variable --arrays --pointers --structs --show // Enable multi-line checking activate-multi-line-match __CPROVER_threads_exited \(\) -> TOP @ \[14\] @@ -14,7 +14,6 @@ __CPROVER_pipe_count \(\) -> 00000000000000000000000000000000 @ \[11\] __CPROVER_malloc_size \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[8\] __CPROVER_next_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[10\] __CPROVER_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[13\] -do_arrays#return_value \(\) -> TOP @ \[49\] main#return_value \(\) -> TOP @ \[1\] do_arrays::1::bool_ \(\) -> TOP @ \[16\] do_arrays::1::bool_1 \(\) -> TOP @ \[17\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/sensitivity_dependency_pointers.c b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/sensitivity_dependency_pointers.c index a3904603f7f..1c3851d5eb7 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/sensitivity_dependency_pointers.c +++ b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/sensitivity_dependency_pointers.c @@ -1,8 +1,3 @@ -int main() -{ - do_pointers(); -} - void do_pointers() { int bool_; @@ -28,3 +23,8 @@ void do_pointers() int j=*y_p; } + +int main() +{ + do_pointers(); +} diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc index 4e83206172b..e18e4451968 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_dependency_pointers.c ---variable --arrays --pointers --structs +--variable --arrays --pointers --structs --show // Enable multi-line checking activate-multi-line-match __CPROVER_threads_exited \(\) -> TOP @ \[14\] @@ -14,7 +14,6 @@ __CPROVER_pipe_count \(\) -> 00000000000000000000000000000000 @ \[11\] __CPROVER_malloc_size \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[8\] __CPROVER_next_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[10\] __CPROVER_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[13\] -do_pointers#return_value \(\) -> TOP @ \[42\] main#return_value \(\) -> TOP @ \[1\] do_pointers::1::bool_ \(\) -> TOP @ \[16\] do_pointers::1::bool_1 \(\) -> TOP @ \[17\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-structs/sensitivity_dependency_structs.c b/regression/goto-analyzer/sensitivity-last-written-locations-structs/sensitivity_dependency_structs.c index 7fc2119023e..56ae53c041a 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-structs/sensitivity_dependency_structs.c +++ b/regression/goto-analyzer/sensitivity-last-written-locations-structs/sensitivity_dependency_structs.c @@ -1,8 +1,3 @@ -int main() -{ - do_structs(); -} - struct Ages { int x; int y; @@ -57,3 +52,9 @@ void do_structs() new_age=st; } + +int main() +{ + do_structs(); +} + diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc index 043a899b5f3..e4df2d1d3a6 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_dependency_structs.c ---variable --arrays --pointers --structs +--variable --arrays --pointers --structs --show // Enable multi-line checking activate-multi-line-match __CPROVER_threads_exited \(\) -> TOP @ \[14\] @@ -14,7 +14,6 @@ __CPROVER_pipe_count \(\) -> 00000000000000000000000000000000 @ \[11\] __CPROVER_malloc_size \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[8\] __CPROVER_next_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[10\] __CPROVER_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[13\] -do_structs#return_value \(\) -> TOP @ \[52\] main#return_value \(\) -> TOP @ \[1\] do_structs::1::bool_ \(\) -> TOP @ \[16\] do_structs::1::bool_1 \(\) -> TOP @ \[17\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-variables/sensitivity_dependency_variables.c b/regression/goto-analyzer/sensitivity-last-written-locations-variables/sensitivity_dependency_variables.c index c584f97f49b..a0551df37fc 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-variables/sensitivity_dependency_variables.c +++ b/regression/goto-analyzer/sensitivity-last-written-locations-variables/sensitivity_dependency_variables.c @@ -1,10 +1,5 @@ int global_x; // Should assign to 0. -int main() -{ - do_variables(); -} - void do_variables() { int bool_; @@ -61,3 +56,8 @@ void do_variables() y=10; x=20; } + +int main() +{ + do_variables(); +} diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc index 753fd2c0f75..24b62b9191a 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_dependency_variables.c ---variable --arrays --pointers --structs +--variable --arrays --pointers --structs --show // Enable multi-line checking activate-multi-line-match __CPROVER_threads_exited \(\) -> TOP @ \[14\] @@ -15,7 +15,6 @@ __CPROVER_pipe_count \(\) -> 00000000000000000000000000000000 @ \[11\] __CPROVER_malloc_size \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[8\] __CPROVER_next_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[10\] __CPROVER_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[13\] -do_variables#return_value \(\) -> TOP @ \[59\] main#return_value \(\) -> TOP @ \[1\] do_variables::1::bool_ \(\) -> TOP @ \[17\] do_variables::1::bool_1 \(\) -> TOP @ \[18\] From c02a0a70ccf8820a79cd4892fd60b4484c95283a Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Thu, 18 Jan 2018 11:27:13 +0000 Subject: [PATCH 182/342] Add a common interface for read/write operations on abstract_objectt's --- .../abstract_enviroment.cpp | 80 +++---------------- .../variable-sensitivity/abstract_object.cpp | 47 +++++++++++ .../variable-sensitivity/abstract_object.h | 14 ++++ .../array_abstract_object.cpp | 49 ++++++++++++ .../array_abstract_object.h | 23 ++++-- .../constant_array_abstract_object.cpp | 49 ++++++++++++ .../constant_array_abstract_object.h | 21 ++++- .../full_struct_abstract_object.h | 29 ++++--- .../pointer_abstract_object.cpp | 47 +++++++++++ .../pointer_abstract_object.h | 19 ++++- .../struct_abstract_object.cpp | 48 +++++++++++ .../struct_abstract_object.h | 19 ++++- .../union_abstract_object.cpp | 48 +++++++++++ .../union_abstract_object.h | 20 ++++- .../variable_sensitivity_domain.cpp | 3 +- .../constant_array_abstract_object/merge.cpp | 2 +- .../full_struct_abstract_object/merge.cpp | 6 +- 17 files changed, 418 insertions(+), 106 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index c7bb4bb875c..6721312e467 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -68,23 +68,9 @@ abstract_object_pointert abstract_environmentt::eval( member_exprt member_expr(to_member_expr(simplified_expr)); const exprt &parent = member_expr.compound(); - bool is_union = ns.follow(parent.type()).id() == ID_union; - if(is_union) - { - sharing_ptrt union_abstract_object= - std::dynamic_pointer_cast( - eval(parent, ns)); - - return union_abstract_object->read_component(*this, member_expr, ns); - } - else - { // is struct - sharing_ptrt struct_abstract_object= - std::dynamic_pointer_cast( - eval(member_expr.compound(), ns)); - return struct_abstract_object->read_component(*this, member_expr, ns); - } + abstract_object_pointert parent_abstract_object=eval(parent, ns); + return parent_abstract_object->read(*this, member_expr, ns); } else if(simplified_id==ID_address_of) { @@ -98,20 +84,18 @@ abstract_object_pointert abstract_environmentt::eval( 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)); + abstract_object_pointert pointer_abstract_object= + eval(dereference.pointer(), ns); - return pointer_abstract_object->read_dereference(*this, ns); + return pointer_abstract_object->read(*this, nil_exprt(), 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)); + abstract_object_pointert array_abstract_object= + eval(index_expr.array(), ns); - return array_abstract_object->read_index(*this, index_expr, ns); + return array_abstract_object->read(*this, index_expr, ns); } else if(simplified_id==ID_array) { @@ -309,56 +293,18 @@ abstract_object_pointert abstract_environmentt::write( // is inserted back into the map if(stack_head_id==ID_index) { - sharing_ptrt array_abstract_object= - std::dynamic_pointer_cast(lhs); - - sharing_ptrt modified_array= - array_abstract_object->write_index( + return lhs->write( *this, ns, remaining_stack, to_index_expr(next_expr), rhs, merge_write); - - return modified_array; } else if(stack_head_id==ID_member) { - - const member_exprt &member_expr = to_member_expr(next_expr); - const exprt &parent = member_expr.compound(); - bool is_union = ns.follow(parent.type()).id() == ID_union; - - if(is_union) - { - sharing_ptrt union_abstract_object= - std::dynamic_pointer_cast(lhs); - - sharing_ptrt modified_union= - union_abstract_object->write_component( - *this, ns, remaining_stack, member_expr, rhs, merge_write); - - return modified_union; - } - else - { - sharing_ptrt struct_abstract_object= - std::dynamic_pointer_cast(lhs); - - 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; - } + return lhs->write( + *this, ns, remaining_stack, to_member_expr(next_expr), rhs, merge_write); } 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; + return lhs->write( + *this, ns, remaining_stack, nil_exprt(), rhs, merge_write); } else { diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 17b869fc90e..5e5d842d001 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -192,6 +192,53 @@ abstract_object_pointert abstract_objectt::expression_transform( return environment.abstract_object_factory(simplified.type(), simplified, ns); } +/** + * A helper function to evaluate an abstract object contained + * within a container object. More precise abstractions may override this + * to return more precise results. + * + * \param env the abstract environment + * \param specifier a modifier expression, such as an array index or field + * specifier used to indicate access to a specific component + * \param ns the current namespace + * + * \return the abstract_objectt representing the value of the read component. + */ +abstract_object_pointert abstract_objectt::read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const +{ + return shared_from_this(); +} + +/** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ +abstract_object_pointert abstract_objectt::write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const +{ + return environment.abstract_object_factory(type(), ns, true); +} + /*******************************************************************\ Function: abstract_objectt::is_top diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index a9561a82677..628ca57a790 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -98,6 +99,19 @@ class abstract_objectt:public std::enable_shared_from_this virtual exprt to_constant() const; + virtual abstract_object_pointert read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const; + + virtual abstract_object_pointert write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const; + virtual void output( std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 7e7d334cdac..254457a369e 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -78,6 +78,55 @@ array_abstract_objectt::array_abstract_objectt( assert(e.type().id()==ID_array); } +/** + * A helper function to evaluate an abstract object contained + * within a container object. More precise abstractions may override this + * to return more precise results. + * + * \param env the abstract environment + * \param specifier a modifier expression, such as an array index or field + * specifier used to indicate access to a specific component + * \param ns the current namespace + * + * \return the abstract_objectt representing the value of the read component. + */ +abstract_object_pointert array_abstract_objectt::read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const +{ + return read_index(env, to_index_expr(specifier), ns); +} + +/** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ +abstract_object_pointert array_abstract_objectt::write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const +{ + return write_index( + environment, ns, stack, to_index_expr(specifier), value, merging_write); +} + + /*******************************************************************\ Function: array_abstract_objectt::read_index diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index 8bc29db4b2c..abee425aace 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -26,21 +26,34 @@ class array_abstract_objectt:public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - virtual abstract_object_pointert read_index( + virtual abstract_object_pointert read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const override; + + virtual abstract_object_pointert write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const override; + +protected: + CLONE + + abstract_object_pointert read_index( const abstract_environmentt &env, const index_exprt &index, const namespacet &ns) const; - virtual sharing_ptrt write_index( + 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; - -protected: - CLONE }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ARRAY_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 96ea74f4f60..a3aad7ea1ce 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -205,6 +205,55 @@ void constant_array_abstract_objectt::output( } } +/** + * A helper function to evaluate an abstract object contained + * within a container object. More precise abstractions may override this + * to return more precise results. + * + * \param env the abstract environment + * \param specifier a modifier expression, such as an array index or field + * specifier used to indicate access to a specific component + * \param ns the current namespace + * + * \return the abstract_objectt representing the value of the read component. + */ +abstract_object_pointert constant_array_abstract_objectt::read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const +{ + return read_index(env, to_index_expr(specifier), ns); +} + +/** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ +abstract_object_pointert constant_array_abstract_objectt::write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const +{ + return write_index( + environment, ns, stack, to_index_expr(specifier), value, + merging_write); +} + /*******************************************************************\ Function: constant_array_abstract_objectt::read_index diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index d5685aaa20d..a0ffa8f8e1d 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -35,22 +35,35 @@ class constant_array_abstract_objectt:public array_abstract_objectt void output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; - virtual abstract_object_pointert read_index( + virtual abstract_object_pointert read( const abstract_environmentt &env, - const index_exprt &index, + const exprt &specifier, const namespacet &ns) const override; - virtual sharing_ptrt write_index( + virtual abstract_object_pointert write( abstract_environmentt &environment, const namespacet &ns, const std::stack stack, - const index_exprt &index_expr, + const exprt &specifier, const abstract_object_pointert value, bool merging_write) const override; protected: CLONE + abstract_object_pointert read_index( + const abstract_environmentt &env, + const index_exprt &index, + const namespacet &ns) const; + + 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; + virtual abstract_object_pointert merge( abstract_object_pointert other) const override; diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 5eafe93951b..fa93d4d46c6 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -31,21 +31,6 @@ class full_struct_abstract_objectt:public struct_abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - - // struct interface - virtual abstract_object_pointert read_component( - const abstract_environmentt &environment, - const member_exprt &member_expr, - const namespacet& ns) const 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) const override; - virtual void output( std::ostream &out, const class ai_baset &ai, @@ -64,6 +49,20 @@ class full_struct_abstract_objectt:public struct_abstract_objectt protected: CLONE + // struct interface + virtual abstract_object_pointert read_component( + const abstract_environmentt &environment, + const member_exprt &member_expr, + const namespacet& ns) const 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) const override; + 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 diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index 74790fb8dd5..b02181f0f02 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -77,6 +77,53 @@ pointer_abstract_objectt::pointer_abstract_objectt( assert(e.type().id()==ID_pointer); } +/** + * A helper function to evaluate an abstract object contained + * within a container object. More precise abstractions may override this + * to return more precise results. + * + * \param env the abstract environment + * \param specifier a modifier expression, such as an array index or field + * specifier used to indicate access to a specific component + * \param ns the current namespace + * + * \return the abstract_objectt representing the value of the read component. + */ +abstract_object_pointert pointer_abstract_objectt::read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const +{ + return read_dereference(env, ns); +} + +/** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ +abstract_object_pointert pointer_abstract_objectt::write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const +{ + return write_dereference(environment, ns, stack, value, merging_write); +} + /*******************************************************************\ Function: pointer_abstract_objectt::read_dereference diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index 26d0632214f..935e7d54ac6 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -27,6 +27,22 @@ class pointer_abstract_objectt:public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); + virtual abstract_object_pointert read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const override; + + virtual abstract_object_pointert write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const override; + +protected: + CLONE + // pointer interface virtual abstract_object_pointert read_dereference( const abstract_environmentt &env, const namespacet &ns) const; @@ -37,9 +53,6 @@ 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 e559e390be4..d50199190c0 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -78,6 +78,54 @@ struct_abstract_objectt::struct_abstract_objectt( assert(ns.follow(e.type()).id()==ID_struct); } +/** + * A helper function to evaluate an abstract object contained + * within a container object. More precise abstractions may override this + * to return more precise results. + * + * \param env the abstract environment + * \param specifier a modifier expression, such as an array index or field + * specifier used to indicate access to a specific component + * \param ns the current namespace + * + * \return the abstract_objectt representing the value of the read component. + */ +abstract_object_pointert struct_abstract_objectt::read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const +{ + return this->read_component(env, to_member_expr(specifier), ns); +} + +/** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ +abstract_object_pointert struct_abstract_objectt::write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const +{ + return this->write_component( + environment, ns, stack, to_member_expr(specifier), value, merging_write); +} + /*******************************************************************\ Function: struct_abstract_objectt::read_component diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index bbded930463..f3fdab164ad 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -25,6 +25,22 @@ class struct_abstract_objectt:public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); + virtual abstract_object_pointert read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const override; + + virtual abstract_object_pointert write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const override; + +protected: + CLONE + // struct interface virtual abstract_object_pointert read_component( const abstract_environmentt &environment, @@ -38,9 +54,6 @@ 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 diff --git a/src/analyses/variable-sensitivity/union_abstract_object.cpp b/src/analyses/variable-sensitivity/union_abstract_object.cpp index aec3eb457d9..ecf7a1054c9 100644 --- a/src/analyses/variable-sensitivity/union_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/union_abstract_object.cpp @@ -77,6 +77,54 @@ union_abstract_objectt::union_abstract_objectt( assert(ns.follow(expr.type()).id()==ID_union); } +/** + * A helper function to evaluate an abstract object contained + * within a container object. More precise abstractions may override this + * to return more precise results. + * + * \param env the abstract environment + * \param specifier a modifier expression, such as an array index or field + * specifier used to indicate access to a specific component + * \param ns the current namespace + * + * \return the abstract_objectt representing the value of the read component. + */ +abstract_object_pointert union_abstract_objectt::read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const +{ + return read_component(env, to_member_expr(specifier), ns); +} + +/** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ +abstract_object_pointert union_abstract_objectt::write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const +{ + return write_component( + environment, ns, stack, to_member_expr(specifier), value, merging_write); +} + /*******************************************************************\ Function: union_abstract_objectt::read_component diff --git a/src/analyses/variable-sensitivity/union_abstract_object.h b/src/analyses/variable-sensitivity/union_abstract_object.h index e9c9a76807a..9d5659ec76a 100644 --- a/src/analyses/variable-sensitivity/union_abstract_object.h +++ b/src/analyses/variable-sensitivity/union_abstract_object.h @@ -25,6 +25,22 @@ class union_abstract_objectt:public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); + virtual abstract_object_pointert read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const override; + + virtual abstract_object_pointert write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const override; + +protected: + CLONE + // union interface virtual abstract_object_pointert read_component( const abstract_environmentt &environment, @@ -38,10 +54,6 @@ class union_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_UNION_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 1a4041052e5..7267ccac06f 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -438,10 +438,11 @@ void variable_sensitivity_domaint::transform_function_call( assert(pointer_value); // Write top to the pointer - pointer_value->write_dereference( + pointer_value->write( abstract_state, ns, std::stack(), + nil_exprt(), abstract_state.abstract_object_factory( called_arg.type().subtype(), ns, true), false); } 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 964084489a6..b80ba724121 100644 --- a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp @@ -59,7 +59,7 @@ class array_utilt constant_array_abstract_object_pointert array_object, const index_exprt &index) const { - return array_object->read_index(enviroment, index, ns)->to_constant(); + return array_object->read(enviroment, index, ns)->to_constant(); } private: 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 7c888c38421..e3c686c4663 100644 --- a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp @@ -41,7 +41,7 @@ class struct_utilt full_struct_abstract_objectt::constant_struct_pointert struct_object, const member_exprt &component) const { - return struct_object->read_component( + return struct_object->read( enviroment, component, ns)->to_constant(); } @@ -59,8 +59,8 @@ class struct_utilt for(const exprt &op : starting_value.operands()) { const auto &component=struct_type.components()[comp_index]; - std::shared_ptr new_result= - result->write_component( + std::shared_ptr new_result= + result->write( enviroment, ns, std::stack(), From dd35cb1edc17b534ab9d71b3b5fbd5d781336bf0 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Thu, 18 Jan 2018 11:59:19 +0000 Subject: [PATCH 183/342] Avoid direct manipulation of abstract_objectt::top --- .../variable-sensitivity/abstract_object.cpp | 4 +-- .../variable-sensitivity/abstract_object.h | 30 ++++++++++++++++--- .../constant_array_abstract_object.cpp | 8 ++--- .../constant_pointer_abstract_object.cpp | 9 +++++- .../full_struct_abstract_object.cpp | 4 +-- 5 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 5e5d842d001..e9b9ce4d34a 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -133,14 +133,14 @@ Function: abstract_objectt::abstract_object_merge abstract_object_pointert abstract_objectt::abstract_object_merge( const abstract_object_pointert other) const { - if(top) + if(is_top()) return shared_from_this(); if(other->bottom) return shared_from_this(); internal_abstract_object_pointert merged=mutable_clone(); - merged->top=true; + merged->make_top(); merged->bottom=false; return merged; } diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 628ca57a790..d8e94ec5194 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -137,11 +137,33 @@ class abstract_objectt:public std::enable_shared_from_this std::ostream &out, const abstract_objectt::locationst &locations); + // Const versions must perform copy-on-write + abstract_object_pointert make_top() const + { + if(is_top()) + return shared_from_this(); + + internal_abstract_object_pointert clone = mutable_clone(); + clone->make_top(); + return clone; + } + + abstract_object_pointert clear_top() const + { + if(!is_top()) + return shared_from_this(); + + internal_abstract_object_pointert clone = mutable_clone(); + clone->clear_top(); + return clone; + } + private: // To enforce copy-on-write these are private and have read-only accessors typet t; bool bottom; locationst last_written_locations; + bool top; abstract_object_pointert abstract_object_merge( const abstract_object_pointert other) const; @@ -164,10 +186,6 @@ class abstract_objectt:public std::enable_shared_from_this virtual void update_sub_elements(const locationst &locations) {} - bool top; - - // 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; @@ -179,6 +197,10 @@ class abstract_objectt:public std::enable_shared_from_this const std::map &map1, const std::map &map2, std::map &out_map); + + // The one exception is merge in descendant classes, which needs this + virtual void make_top() { top=true; } + virtual void clear_top() { top=false; } }; template diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index a3aad7ea1ce..b29461bf17d 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -81,7 +81,7 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( map[mp_integer(index)]=environment.eval(entry, ns); ++index; } - top=false; + clear_top(); } } @@ -354,7 +354,7 @@ sharing_ptrt { if(is_top()) { - copy->top=false; + copy->clear_top(); } copy->map[index_value]=value; @@ -390,7 +390,7 @@ sharing_ptrt if(is_top()) { - copy->top=false; + copy->clear_top(); } copy->map[index_value]=environment.write( array_entry, value, stack, ns, merging_write); @@ -407,7 +407,7 @@ sharing_ptrt array_entry.second, value, stack, ns, true); if(is_top()) { - copy->top=false; + copy->clear_top(); } } diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 7e685b1123e..7231774cb35 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -96,7 +96,14 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( value_stack(e, environment, ns) { assert(e.type().id()==ID_pointer); - top=value_stack.is_top_value(); + if(value_stack.is_top_value()) + { + make_top(); + } + else + { + clear_top(); + } } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 64ace377e9d..08baa5ab86a 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -204,7 +204,7 @@ sharing_ptrt copy->map[c]= environment.write(starting_value, value, stack, ns, merging_write); - copy->top=false; + copy->clear_top(); assert(copy->verify()); return copy; } @@ -244,7 +244,7 @@ sharing_ptrt else { copy->map[c]=value; - copy->top=false; + copy->clear_top(); assert(!copy->is_bottom()); } From c3d14e7dfb08e72ef39d54eb84f5e18d72d21777 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Thu, 18 Jan 2018 14:24:38 +0000 Subject: [PATCH 184/342] Factor out last_written_location into it's own abstract_objectt --- src/analyses/Makefile | 1 + .../abstract_enviroment.cpp | 13 +- .../variable-sensitivity/abstract_object.cpp | 134 ++------ .../variable-sensitivity/abstract_object.h | 28 +- .../constant_array_abstract_object.cpp | 6 - .../dependency_context_abstract_object.cpp | 321 ++++++++++++++++++ .../dependency_context_abstract_object.h | 182 ++++++++++ .../full_struct_abstract_object.cpp | 8 - .../full_struct_abstract_object.h | 4 +- .../variable_sensitivity_domain.cpp | 5 +- .../variable_sensitivity_object_factory.cpp | 50 +-- .../variable_sensitivity_object_factory.h | 1 + 12 files changed, 585 insertions(+), 168 deletions(-) create mode 100644 src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/dependency_context_abstract_object.h diff --git a/src/analyses/Makefile b/src/analyses/Makefile index 0fbf7111f5a..b49ed92c594 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -39,6 +39,7 @@ SRC = ai.cpp \ variable-sensitivity/array_abstract_object.cpp \ variable-sensitivity/constant_abstract_value.cpp \ variable-sensitivity/constant_pointer_abstract_object.cpp \ + variable-sensitivity/dependency_context_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 6721312e467..6a1bf65515d 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -74,9 +74,8 @@ abstract_object_pointert abstract_environmentt::eval( } else if(simplified_id==ID_address_of) { - sharing_ptrt pointer_object= - std::dynamic_pointer_cast( - abstract_object_factory(simplified_expr.type(), simplified_expr, ns)); + abstract_object_pointert pointer_object= + abstract_object_factory(simplified_expr.type(), simplified_expr, ns); // Store the abstract object in the pointer return pointer_object; @@ -239,9 +238,7 @@ bool abstract_environmentt::assign( if(final_value != map[symbol_expr]) { - map[symbol_expr]=final_value - ->update_last_written_locations( - value->get_last_written_locations(), false); + map[symbol_expr]=final_value; } } return true; @@ -634,10 +631,6 @@ void abstract_environmentt::output( out << entry.first.get_identifier() << " (" << ") -> "; entry.second->output(out, ai, ns); - - out << " @ "; - entry.second->output_last_written_locations( - out, entry.second->get_last_written_locations()); out << "\n"; } out << "}\n"; diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index e9b9ce4d34a..25dee869bda 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -133,16 +133,32 @@ Function: abstract_objectt::abstract_object_merge abstract_object_pointert abstract_objectt::abstract_object_merge( const abstract_object_pointert other) const { - if(is_top()) - return shared_from_this(); - if(other->bottom) - return shared_from_this(); - + if(is_top() || other->bottom) + return this->abstract_object_merge_internal(other); internal_abstract_object_pointert merged=mutable_clone(); merged->make_top(); merged->bottom=false; - return merged; + return merged->abstract_object_merge_internal(other); +} + +/** + * Helper function for abstract_objectt::abstract_object_merge to perform any + * additional actions after the base abstract_object_merge has completed it's + * actions but immediately prior to it returning. As such, this function gives + * the ability to perform additional work for a merge. + * + * This default implementation just returns itself. + * + * \param other the object to merge with this + * + * \return the result of the merge + */ +abstract_object_pointert abstract_objectt::abstract_object_merge_internal( + const abstract_object_pointert other) const +{ + // Default implementation + return shared_from_this(); } /*******************************************************************\ @@ -357,15 +373,6 @@ abstract_object_pointert abstract_objectt::merge( // If no modifications, we will return the original pointer out_modifications=result!=op1; - locationst get_location_union = op1->get_location_union( - op2->get_last_written_locations()); - // If the union is larger than the initial set, then update. - if(get_location_union.size() > op1->get_last_written_locations().size()) - { - out_modifications=true; - result=result->update_last_written_locations(get_location_union, false); - } - return result; } @@ -410,55 +417,13 @@ abstract_object_pointert abstract_objectt::update_last_written_locations( const locationst &locations, bool update_sub_elements) const { - internal_abstract_object_pointert clone=mutable_clone(); - clone->set_last_written_locations(locations); if(update_sub_elements) + { + internal_abstract_object_pointert clone=mutable_clone(); clone->update_sub_elements(locations); - return clone; -} - -/*******************************************************************\ - -Function: abstract_objectt::get_location_union - - Inputs: - Set of locations unioned - - Outputs: - The union of the two sets - - Purpose: Takes the location set of the current object, and unions it - with the provided set. - -\*******************************************************************/ - -abstract_objectt::locationst abstract_objectt::get_location_union(const locationst &locations) const -{ - locationst existing_locations=get_last_written_locations(); - existing_locations.insert(locations.begin(), locations.end()); - - return existing_locations; -} - -/*******************************************************************\ - -Function: abstract_objectt::set_last_written_locations - - Inputs: - Set of locations to be written - - Outputs: - Void - - Purpose: Writes the provided set to the object. - - For mutable objects. - -\*******************************************************************/ - -void abstract_objectt::set_last_written_locations(const locationst &locations) -{ - last_written_locations=locations; + return clone; + } + return shared_from_this(); } /*******************************************************************\ @@ -477,51 +442,8 @@ Function: abstract_objectt::get_last_written_locations abstract_objectt::locationst abstract_objectt::get_last_written_locations() const { - return last_written_locations; + return {}; } -/*******************************************************************\ - -Function: abstract_objectt::output_last_written_location - - Inputs: - object - the object to read information from - out - the stream to write to - ai - the abstract interpreter that contains this domain - ns - the current namespace - - Outputs: None - - Purpose: Print out all last written locations for a specified - object - -\*******************************************************************/ - -void abstract_objectt::output_last_written_locations( - std::ostream &out, - const abstract_objectt::locationst &locations) -{ - out << "["; - bool comma=false; - - std::set sorted_locations; - for(auto location: locations) - { - sorted_locations.insert(location->location_number); - } - for (auto location_number: sorted_locations) - { - if(!comma) - { - out << location_number; - comma=true; - } - else - { - out << ", " << location_number; - } - } - out << "]"; -} diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index d8e94ec5194..0ed38ddea52 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -128,14 +128,10 @@ class abstract_objectt:public std::enable_shared_from_this abstract_object_pointert op2, bool &out_modifications); - abstract_object_pointert update_last_written_locations( + virtual abstract_object_pointert update_last_written_locations( const locationst &locations, const bool update_sub_elements) const; - locationst get_last_written_locations() const; - - static void output_last_written_locations( - std::ostream &out, - const abstract_objectt::locationst &locations); + virtual locationst get_last_written_locations() const; // Const versions must perform copy-on-write abstract_object_pointert make_top() const @@ -162,12 +158,18 @@ 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; - locationst last_written_locations; bool top; - abstract_object_pointert abstract_object_merge( + // Hooks to allow a sub-class to perform its own operations on + // setting/clearing top + virtual void make_top_internal() {} + virtual void clear_top_internal() {} + + // Hook for a subclass to perform any additional operations as + // part of an abstract_object_merge + virtual abstract_object_pointert abstract_object_merge_internal( const abstract_object_pointert other) const; - locationst get_location_union(const locationst &locations) const; + protected: template using internal_sharing_ptrt=std::shared_ptr; @@ -181,11 +183,11 @@ class abstract_objectt:public std::enable_shared_from_this return internal_abstract_object_pointert(new abstract_objectt(*this)); } - void set_last_written_locations(const locationst &locations); - virtual void update_sub_elements(const locationst &locations) {} + abstract_object_pointert abstract_object_merge( + const abstract_object_pointert other) const; bool should_use_base_merge(const abstract_object_pointert other) const; @@ -199,8 +201,8 @@ class abstract_objectt:public std::enable_shared_from_this std::map &out_map); // The one exception is merge in descendant classes, which needs this - virtual void make_top() { top=true; } - virtual void clear_top() { top=false; } + void make_top() { top=true; this->make_top_internal(); } + void clear_top() { top=false; this->clear_top_internal(); } }; template diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index b29461bf17d..db3a4b30d0b 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -193,12 +193,6 @@ void constant_array_abstract_objectt::output( { out << "[" << entry.first << "] = "; entry.second->output(out, ai, ns); - - // Start outputting specific last_written_locations - out << " @ "; - output_last_written_locations(out, - entry.second->get_last_written_locations()); - out << "\n"; } out << "}"; diff --git a/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp b/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp new file mode 100644 index 00000000000..fcbbd138507 --- /dev/null +++ b/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp @@ -0,0 +1,321 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Chris Ryder, chris.ryder@diffblue.com + +\*******************************************************************/ + +#include +#include +#include +#include "dependency_context_abstract_object.h" +#include "full_struct_abstract_object.h" + +void dependency_context_abstract_objectt::set_child( + const abstract_object_pointert &child) +{ + child_abstract_object = child; +} + +void dependency_context_abstract_objectt::make_top_internal() +{ + if(!child_abstract_object->is_top()) + set_child(child_abstract_object->make_top()); +} + +void dependency_context_abstract_objectt::clear_top_internal() +{ + if(child_abstract_object->is_top()) + set_child(child_abstract_object->clear_top()); +} + +/*******************************************************************\ + +Function: dependency_context_abstract_objectt::update_last_written_locations + + Inputs: + Set of locations to be written. + + Outputs: + An abstract_object_pointer pointing to the cloned, updated object. + + Purpose: Creates a mutable clone of the current object, and updates + the last written location map with the provided location(s). + + For immutable objects. + +\*******************************************************************/ +abstract_object_pointert + dependency_context_abstract_objectt::update_last_written_locations( + const abstract_objectt::locationst &locations, + const bool update_sub_elements) const +{ + const auto &result= + std::dynamic_pointer_cast( + mutable_clone()); + + result->set_child(child_abstract_object->update_last_written_locations( + locations, update_sub_elements)); + + result->set_last_written_locations(locations); + return result; +} + +abstract_objectt::locationst + dependency_context_abstract_objectt::get_last_written_locations() const +{ + return last_written_locations; +} + +/** + * A helper function to evaluate an abstract object contained + * within a container object. More precise abstractions may override this + * to return more precise results. + * + * \param env the abstract environment + * \param specifier a modifier expression, such as an array index or field + * specifier used to indicate access to a specific component + * \param ns the current namespace + * + * \return the abstract_objectt representing the value of the read component. + * For the dependency context, the operation is simply delegated to the + * child object + */ +abstract_object_pointert dependency_context_abstract_objectt::read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const +{ + return child_abstract_object->read(env, specifier, ns); +} + +/** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ +abstract_object_pointert dependency_context_abstract_objectt::write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const +{ + // But delegate the write to the child + abstract_object_pointert updated_child= + child_abstract_object->write( + environment, ns, stack, specifier, value, merging_write); + + // Only perform an update if the write to the child has in fact changed it... + // FIXME: But do we still want to record the write??? + if(updated_child == child_abstract_object) + return shared_from_this(); + + // Need to ensure the result of the write is still wrapped in a dependency + // context + const auto &result= + std::dynamic_pointer_cast( + mutable_clone()); + + // Update the child and record the updated write locations + result->set_child(updated_child); + result->set_last_written_locations(value->get_last_written_locations()); + + return result; +} + +/** + * Create a new abstract object that is the result of merging this abstract + * object with a given abstract_object + * + * \param other the abstract object to merge with + * + * \return the result of the merge, or 'this' if the merge would not change + * the current abstract object + */ +abstract_object_pointert dependency_context_abstract_objectt::merge( + abstract_object_pointert other) const +{ + auto cast_other= + std::dynamic_pointer_cast(other); + + if(cast_other) + { + bool child_modified=false; + + auto merged_child= + abstract_objectt::merge( + child_abstract_object, cast_other->child_abstract_object, + child_modified); + + abstract_objectt::locationst location_union=get_location_union( + cast_other->get_last_written_locations()); + // If the union is larger than the initial set, then update. + bool merge_locations = + location_union.size()>get_last_written_locations().size(); + + if(child_modified || merge_locations) + { + const auto &result= + std::dynamic_pointer_cast( + mutable_clone()); + if(child_modified) + { + result->set_child(merged_child); + } + if(merge_locations) + { + result->set_last_written_locations(location_union); + } + + return result; + } + + return shared_from_this(); + } + + return abstract_objectt::merge(other); +} + +/** + * Helper function for abstract_objectt::abstract_object_merge to perform any + * additional actions after the base abstract_object_merge has completed it's + * actions but immediately prior to it returning. As such, this function gives + * the ability to perform additional work for a merge. + * + * For the dependency context, this additional work is the tracking of + * last_written_locations across the merge + * + * \param other the object to merge with this + * + * \return the result of the merge + */ +abstract_object_pointert + dependency_context_abstract_objectt::abstract_object_merge_internal( + const abstract_object_pointert other) const +{ + abstract_objectt::locationst location_union = get_location_union( + other->get_last_written_locations()); + + // If the union is larger than the initial set, then update. + if(location_union.size() > get_last_written_locations().size()) + { + abstract_object_pointert result = mutable_clone(); + return result->update_last_written_locations(location_union, false); + } + return shared_from_this(); +} + +/** + * Sets the last written locations for this context + * + * \param locations the locations to set + */ +void dependency_context_abstract_objectt::set_last_written_locations( + const abstract_objectt::locationst &locations) +{ + last_written_locations=locations; +} + +/** + * Try to resolve an expression with the maximum level of precision + * available. + * + * \param expr the expression to evaluate and find the result of. This will + * be the symbol referred to be op0() + * \param environment the abstract environment in which to resolve 'expr' + * \param ns the current namespace + * + * \return the resolved expression + */ +abstract_object_pointert + dependency_context_abstract_objectt::expression_transform( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const +{ + return child_abstract_object->expression_transform(expr, environment, ns); +} + +/** + * Output a representation of the value of this abstract object + * + * \param out the stream to write to + * \param ai the abstract interpreter that contains the abstract domain + * (that contains the object ... ) + * \param ns the current namespace + */ +void dependency_context_abstract_objectt::output( + std::ostream &out, const ai_baset &ai, const namespacet &ns) const +{ + child_abstract_object->output(out, ai, ns); + + // Output last written locations immediately following the child output + out << " @ "; + output_last_written_locations(out, last_written_locations); +} + +/** + * Construct the union of the location set of the current object, and a + * the provided location set. + * + * \param locations the set of locations to be unioned with this context + * + * \return the union of this objects location set, and 'locations' + */ +abstract_objectt::locationst + dependency_context_abstract_objectt::get_location_union( + const locationst &locations) const +{ + locationst existing_locations=get_last_written_locations(); + existing_locations.insert(locations.begin(), locations.end()); + + return existing_locations; +} + +/** + * Internal helper function to format and output a given set of locations + * + * \param out the stream on which to output the locations + * \param locations the set of locations to output + */ +void dependency_context_abstract_objectt::output_last_written_locations( + std::ostream &out, + const abstract_objectt::locationst &locations) +{ + out << "["; + bool comma=false; + + std::set sorted_locations; + for(auto location : locations) + { + sorted_locations.insert(location->location_number); + } + + for(auto location_number : sorted_locations) + { + if(!comma) + { + out << location_number; + comma=true; + } + else + { + out << ", " << location_number; + } + } + out << "]"; +} diff --git a/src/analyses/variable-sensitivity/dependency_context_abstract_object.h b/src/analyses/variable-sensitivity/dependency_context_abstract_object.h new file mode 100644 index 00000000000..613d616823d --- /dev/null +++ b/src/analyses/variable-sensitivity/dependency_context_abstract_object.h @@ -0,0 +1,182 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Chris Ryder, chris.ryder@diffblue.com + +\*******************************************************************/ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_DEPENDENCY_CONTEXT_ABSTRACT_OBJECT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_DEPENDENCY_CONTEXT_ABSTRACT_OBJECT_H + +#include +#include +#include +#include "array_abstract_object.h" + +/** + * General implementation of an abstract_objectt which tracks the + * last written locations for a given abstract_objectt. + * Instances of this class are constructed with an abstract_object_pointert, + * to which most operations are delegated, while at the same time this + * class handles the tracking of the 'last_written_location' information. + * + * Instances of this class are best constructed via the templated version + * of this, 'context_abstract_objectt' which provides the same + * constructors as the standard 'abstract_objectt' class. + */ +class dependency_context_abstract_objectt: public abstract_objectt +{ +public: + // These constructors mirror those in the base abstract_objectt, but with + // the addition of an extra argument which is the abstract_objectt to wrap. + explicit dependency_context_abstract_objectt( + const abstract_object_pointert child, + const typet &type): + abstract_objectt(type) + { + child_abstract_object = child; + } + + dependency_context_abstract_objectt( + const abstract_object_pointert child, + const typet &type, + bool top, + bool bottom): + abstract_objectt(type, top, bottom) + { + child_abstract_object = child; + } + + explicit dependency_context_abstract_objectt( + const abstract_object_pointert child, + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns): + abstract_objectt(expr, environment, ns) + { + child_abstract_object = child; + } + + virtual ~dependency_context_abstract_objectt() {} + + // Standard abstract_objectt interface + + virtual abstract_objectt::locationst get_last_written_locations() + const override; + + virtual abstract_object_pointert update_last_written_locations( + const abstract_objectt::locationst &locations, + const bool update_sub_elements) const override; + + locationst get_location_union(const locationst &locations) const; + + virtual const typet &type() const + { + return child_abstract_object->type(); + } + + virtual bool is_top() const override + { + return child_abstract_object->is_top(); + } + + virtual bool is_bottom() const override + { + return child_abstract_object->is_bottom(); + } + + abstract_object_pointert expression_transform( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const; + + virtual exprt to_constant() const override + { + return child_abstract_object->to_constant(); + } + + virtual void output( + std::ostream &out, const class ai_baset &ai, const namespacet &ns) const + override; + + +protected: + CLONE + + virtual abstract_object_pointert merge( + abstract_object_pointert other) const override; + + virtual abstract_object_pointert read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const override; + + virtual abstract_object_pointert write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const override; + + static void output_last_written_locations( + std::ostream &out, + const abstract_objectt::locationst &locations); + +private: + // To enforce copy-on-write these are private and have read-only accessors + abstract_objectt::locationst last_written_locations; + abstract_object_pointert child_abstract_object; + + // These are internal hooks that allow sub-classes to perform additional + // actions when an abstract_object is set/unset to TOP + virtual void make_top_internal() override; + virtual void clear_top_internal() override; + + virtual abstract_object_pointert abstract_object_merge_internal( + const abstract_object_pointert other) const override; + + void set_last_written_locations( + const abstract_objectt::locationst &locations); + + void set_child( + const abstract_object_pointert &child); + +}; + + +/** + * Templated extension of the abstract implementation, used as a wrapper around + * other abstract_objectt classes to enable the factory to instantiate the + * context information + */ +template +class context_abstract_objectt: public dependency_context_abstract_objectt +{ +public: + explicit context_abstract_objectt(const typet &type): + dependency_context_abstract_objectt( + abstract_object_pointert(new AOT(type)), type) {} + + context_abstract_objectt( + const typet &type, + bool top, + bool bottom): + dependency_context_abstract_objectt( + abstract_object_pointert(new AOT(type, top, bottom)), + type, + top, + bottom) {} + + explicit context_abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns): + dependency_context_abstract_objectt( + abstract_object_pointert(new AOT(expr, environment, ns)), + expr, + environment, + ns) {} +}; +// NOLINTNEXTLINE(whitespace/line_length) +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_DEPENDENCY_CONTEXT_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 08baa5ab86a..0c7b7e57fa9 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -185,8 +185,6 @@ sharing_ptrt internal_sharing_ptrt copy( new full_struct_abstract_objectt(*this)); - copy->set_last_written_locations(value->get_last_written_locations()); - if(!stack.empty()) { abstract_object_pointert starting_value; @@ -283,12 +281,6 @@ void full_struct_abstract_objectt::output( } out << "." << entry.first << "="; entry.second->output(out, ai, ns); - - // Start outputting specific last_written_locations - out << " @ "; - output_last_written_locations(out, - entry.second->get_last_written_locations()); - } out << "}"; } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index fa93d4d46c6..8ad38081fbf 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -41,8 +41,6 @@ class full_struct_abstract_objectt:public struct_abstract_objectt typedef std::map struct_mapt; struct_mapt map; - virtual void update_sub_elements(const locationst &locations) override; - abstract_object_pointert merge_constant_structs( constant_struct_pointert other) const; @@ -63,6 +61,8 @@ class full_struct_abstract_objectt:public struct_abstract_objectt const abstract_object_pointert value, bool merging_write) const override; + virtual void update_sub_elements(const locationst &locations) override; + 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 diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 7267ccac06f..090f62e9308 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -431,9 +431,8 @@ void variable_sensitivity_domaint::transform_function_call( { if(called_arg.type().id()==ID_pointer) { - sharing_ptrt pointer_value= - std::dynamic_pointer_cast( - abstract_state.eval(called_arg, ns)); + abstract_object_pointert pointer_value= + abstract_state.eval(called_arg, ns); assert(pointer_value); diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index bde525f855c..6895aff9f32 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -100,36 +100,46 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: switch(abstract_object_type) { case CONSTANT: - return initialize_abstract_object( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object< + context_abstract_objectt>( + followed_type, top, bottom, e, environment, ns); case ARRAY_SENSITIVE: - return initialize_abstract_object( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object< + context_abstract_objectt>( + followed_type, top, bottom, e, environment, ns); case ARRAY_INSENSITIVE: - return initialize_abstract_object( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object< + context_abstract_objectt>( + followed_type, top, bottom, e, environment, ns); case POINTER_SENSITIVE: - return initialize_abstract_object( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object< + context_abstract_objectt>( + followed_type, top, bottom, e, environment, ns); case POINTER_INSENSITIVE: - return initialize_abstract_object( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object< + context_abstract_objectt>( + followed_type, top, bottom, e, environment, ns); case STRUCT_SENSITIVE: - return initialize_abstract_object( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object< + context_abstract_objectt>( + followed_type, top, bottom, e, environment, ns); case STRUCT_INSENSITIVE: - return initialize_abstract_object( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object< + context_abstract_objectt>( + followed_type, top, bottom, e, environment, ns); case UNION_INSENSITIVE: - return initialize_abstract_object( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object< + context_abstract_objectt>( + followed_type, top, bottom, e, environment, ns); case TWO_VALUE: - return initialize_abstract_object( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object< + context_abstract_objectt>( + followed_type, top, bottom, e, environment, ns); default: UNREACHABLE; - return initialize_abstract_object( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object< + context_abstract_objectt>( + 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 b8f4e2381f4..71cb923a412 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include From 76e301493f25f6f1282052edab61e701ed41fcc6 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Thu, 11 Jan 2018 13:57:47 +0000 Subject: [PATCH 185/342] Factor out 'is_modified' logic into to the abstract_object implementations Instead of having the abstract_environment have to know details of the abstract_objects (e.g. last_written_location) in order to decide what has been modified between two environments (e.g. at a 3-way merge), make the individual implementation of abstract_object handle that logic. src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp --- .../abstract_enviroment.cpp | 53 +------- .../variable-sensitivity/abstract_object.cpp | 19 --- .../variable-sensitivity/abstract_object.h | 17 ++- .../dependency_context_abstract_object.cpp | 113 ++++++++++++++++-- .../dependency_context_abstract_object.h | 6 +- 5 files changed, 125 insertions(+), 83 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 6a1bf65515d..e1e28b69f8c 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -717,59 +717,8 @@ std::vector abstract_environmentt::modified_symbols( const auto &second_entry = second.map.find(entry.first); if (second_entry != second.map.end()) { - // for the last written write locations to match - // each location in one must be equal to precisely one location - // in the other - // Since a set can assume at most one match - - const abstract_objectt::locationst &first_write_locations= - entry.second->get_last_written_locations(); - const abstract_objectt::locationst &second_write_locations= - second_entry->second->get_last_written_locations(); - - class location_ordert - { - public: - bool operator()( - goto_programt::const_targett instruction, - goto_programt::const_targett other_instruction) - { - return instruction->location_number> - other_instruction->location_number; - } - }; - - typedef std::set - sorted_locationst; - - sorted_locationst lhs_location; - for(const auto &entry:first_write_locations) - { - lhs_location.insert(entry); - } - - - sorted_locationst rhs_location; - for(const auto &entry:second_write_locations) - { - rhs_location.insert(entry); - } - - abstract_objectt::locationst intersection; - std::set_intersection( - lhs_location.cbegin(), - lhs_location.cend(), - rhs_location.cbegin(), - rhs_location.cend(), - std::inserter(intersection, intersection.end()), - location_ordert()); - bool all_matched=intersection.size()==first_write_locations.size() && - intersection.size()==second_write_locations.size(); - - if (!all_matched) - { + if(second_entry->second->has_been_modified(entry.second)) symbols_diff.push_back(entry.first); - } } } diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 25dee869bda..8860d469916 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -426,24 +426,5 @@ abstract_object_pointert abstract_objectt::update_last_written_locations( return shared_from_this(); } -/*******************************************************************\ - -Function: abstract_objectt::get_last_written_locations - - Inputs: - None - - Outputs: - Set of locations for the provided object. - - Purpose: Getter for last_written_locations - -\*******************************************************************/ - -abstract_objectt::locationst abstract_objectt::get_last_written_locations() const -{ - return {}; -} - diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 0ed38ddea52..15c845df69c 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -123,6 +123,22 @@ class abstract_objectt:public std::enable_shared_from_this return abstract_object_pointert(mutable_clone()); } + /** + * Determine whether 'this' abstract_object has been modified in comparison + * to a previous 'before' state. + * \param before The abstract_object_pointert to use as a reference to + * compare against + * \return true if 'this' is considered to have been modified in comparison + * to 'before', false otherwise. + */ + virtual bool has_been_modified(const abstract_object_pointert before) const + { + // Default implementation, with no other information to go on + // falls back to relying on copy-on-write and pointer inequality + // to indicate if an abstract_objectt has been modified + return this != before.get(); + }; + static abstract_object_pointert merge( abstract_object_pointert op1, abstract_object_pointert op2, @@ -131,7 +147,6 @@ class abstract_objectt:public std::enable_shared_from_this virtual abstract_object_pointert update_last_written_locations( const locationst &locations, const bool update_sub_elements) const; - virtual locationst get_last_written_locations() const; // Const versions must perform copy-on-write abstract_object_pointert make_top() const diff --git a/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp b/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp index fcbbd138507..7e243db8a2c 100644 --- a/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp @@ -114,13 +114,11 @@ abstract_object_pointert dependency_context_abstract_objectt::write( const abstract_object_pointert value, bool merging_write) const { - // But delegate the write to the child abstract_object_pointert updated_child= child_abstract_object->write( environment, ns, stack, specifier, value, merging_write); // Only perform an update if the write to the child has in fact changed it... - // FIXME: But do we still want to record the write??? if(updated_child == child_abstract_object) return shared_from_this(); @@ -132,7 +130,14 @@ abstract_object_pointert dependency_context_abstract_objectt::write( // Update the child and record the updated write locations result->set_child(updated_child); - result->set_last_written_locations(value->get_last_written_locations()); + auto value_context= + std::dynamic_pointer_cast(value); + + if(value_context) + { + result->set_last_written_locations( + value_context->get_last_written_locations()); + } return result; } @@ -207,14 +212,20 @@ abstract_object_pointert dependency_context_abstract_objectt::abstract_object_merge_internal( const abstract_object_pointert other) const { - abstract_objectt::locationst location_union = get_location_union( - other->get_last_written_locations()); + auto other_context= + std::dynamic_pointer_cast(other); - // If the union is larger than the initial set, then update. - if(location_union.size() > get_last_written_locations().size()) + if(other_context) { - abstract_object_pointert result = mutable_clone(); - return result->update_last_written_locations(location_union, false); + abstract_objectt::locationst location_union=get_location_union( + other_context->get_last_written_locations()); + + // If the union is larger than the initial set, then update. + if(location_union.size()>get_last_written_locations().size()) + { + abstract_object_pointert result=mutable_clone(); + return result->update_last_written_locations(location_union, false); + } } return shared_from_this(); } @@ -286,6 +297,90 @@ abstract_objectt::locationst return existing_locations; } +/** + * Determine whether 'this' abstract_object has been modified in comparison + * to a previous 'before' state. + * \param before The abstract_object_pointert to use as a reference to + * compare against + * \return true if 'this' is considered to have been modified in comparison + * to 'before', false otherwise. + */ +bool dependency_context_abstract_objectt::has_been_modified( + const abstract_object_pointert before) const +{ + if(this==before.get()) + { + // copy-on-write means pointer equality implies no modifications + return false; + } + + auto before_context= + std::dynamic_pointer_cast + (before); + + if(!before_context) + { + // The other context is not something we understand, so must assume + // that the abstract_object has been modified + return true; + } + + // Even if the pointers are different, it maybe that it has changed only + // because of a merge operation, rather than an actual write. Given that + // this class has knowledge of where writes have occured, use that + // information to determine if any writes have happened and use that as the + // proxy for whether the value has changed or not. + // + // For two sets of last written locations to match, + // each location in one set must be equal to precisely one location + // in the other, since a set can assume at most one match + + const abstract_objectt::locationst &first_write_locations= + before_context->get_last_written_locations(); + const abstract_objectt::locationst &second_write_locations= + get_last_written_locations(); + + class location_ordert + { + public: + bool operator()( + goto_programt::const_targett instruction, + goto_programt::const_targett other_instruction) + { + return instruction->location_number> + other_instruction->location_number; + } + }; + + typedef std::set + sorted_locationst; + + sorted_locationst lhs_location; + for(const auto &entry : first_write_locations) + { + lhs_location.insert(entry); + } + + sorted_locationst rhs_location; + for(const auto &entry : second_write_locations) + { + rhs_location.insert(entry); + } + + abstract_objectt::locationst intersection; + std::set_intersection( + lhs_location.cbegin(), + lhs_location.cend(), + rhs_location.cbegin(), + rhs_location.cend(), + std::inserter(intersection, intersection.end()), + location_ordert()); + bool all_matched=intersection.size()==first_write_locations.size() && + intersection.size()==second_write_locations.size(); + + return !all_matched; +} + /** * Internal helper function to format and output a given set of locations * diff --git a/src/analyses/variable-sensitivity/dependency_context_abstract_object.h b/src/analyses/variable-sensitivity/dependency_context_abstract_object.h index 613d616823d..1b095cf874e 100644 --- a/src/analyses/variable-sensitivity/dependency_context_abstract_object.h +++ b/src/analyses/variable-sensitivity/dependency_context_abstract_object.h @@ -61,8 +61,8 @@ class dependency_context_abstract_objectt: public abstract_objectt // Standard abstract_objectt interface - virtual abstract_objectt::locationst get_last_written_locations() - const override; + virtual bool has_been_modified(const abstract_object_pointert before) const + override; virtual abstract_object_pointert update_last_written_locations( const abstract_objectt::locationst &locations, @@ -123,6 +123,8 @@ class dependency_context_abstract_objectt: public abstract_objectt std::ostream &out, const abstract_objectt::locationst &locations); + virtual abstract_objectt::locationst get_last_written_locations() const; + private: // To enforce copy-on-write these are private and have read-only accessors abstract_objectt::locationst last_written_locations; From a7254f5c3f6dd640b0f2e3ae18b5b9da635c2859 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Thu, 18 Jan 2018 17:08:26 +0000 Subject: [PATCH 186/342] Refactor and rename update_last_written_locations to be more generic Two main changes: * update_last_written_locations is renamed to update_location_context * the update_sub_element functions/mechanism is replaced with a more generically useful visitor mechanism --- .../variable-sensitivity/abstract_object.cpp | 40 ++++++---------- .../variable-sensitivity/abstract_object.h | 35 +++++++++++--- .../constant_array_abstract_object.cpp | 42 +++++++++-------- .../constant_array_abstract_object.h | 5 +- .../dependency_context_abstract_object.cpp | 46 ++++++++++--------- .../dependency_context_abstract_object.h | 21 ++++++++- .../full_struct_abstract_object.cpp | 42 +++++++++-------- .../full_struct_abstract_object.h | 5 +- .../variable_sensitivity_domain.cpp | 11 +++-- 9 files changed, 142 insertions(+), 105 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 8860d469916..837daebf9a6 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -396,33 +396,21 @@ bool abstract_objectt::should_use_base_merge( return is_top() || other->is_bottom() || other->is_top(); } -/*******************************************************************\ - -Function: abstract_objectt::update_last_written_locations - - Inputs: - Set of locations to be written. - - Outputs: - An abstract_object_pointer pointing to the cloned, updated object. - - Purpose: Creates a mutable clone of the current object, and updates - the last written location map with the provided location(s). - - For immutable objects. - -\*******************************************************************/ - -abstract_object_pointert abstract_objectt::update_last_written_locations( - const locationst &locations, - bool update_sub_elements) const +/** + * Update the location context for an abstract object, potentially + * propogating the update to any children of this abstract object. + * + * \param locations the set of locations to be updated + * \param update_sub_elements if true, propogate the update operation to any + * children of this abstract object + * + * \return a clone of this abstract object with it's location context + * updated + */ +abstract_object_pointert abstract_objectt::update_location_context( + const locationst &locations, + const bool update_sub_elements) const { - if(update_sub_elements) - { - internal_abstract_object_pointert clone=mutable_clone(); - clone->update_sub_elements(locations); - return clone; - } return shared_from_this(); } diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 15c845df69c..3c46cd7cb31 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -144,9 +144,9 @@ class abstract_objectt:public std::enable_shared_from_this abstract_object_pointert op2, bool &out_modifications); - virtual abstract_object_pointert update_last_written_locations( - const locationst &locations, - const bool update_sub_elements) const; + virtual abstract_object_pointert update_location_context( + const locationst &locations, + const bool update_sub_elements) const; // Const versions must perform copy-on-write abstract_object_pointert make_top() const @@ -169,6 +169,32 @@ class abstract_objectt:public std::enable_shared_from_this return clone; } + /** + * Pure virtual interface required of a client that can apply a copy-on-write + * operation to a given abstract_object_pointert. + */ + struct abstract_object_visitort + { + virtual abstract_object_pointert visit( + const abstract_object_pointert element) const = 0; + }; + + /** + * Apply a visitor operation to all sub elements of this abstract_object. + * A sub element might be a member of a struct, or an element of an array, + * for instance, but this is entirely determined by the particular + * derived instance of abstract_objectt. + * + * \param visitor an instance of a visitor class that will be applied to + * all sub elements + * \return A new abstract_object if it's contents is modifed, or this if + * no modification is needed + */ + virtual abstract_object_pointert visit_sub_elements( + const abstract_object_visitort &visitor) const + { return shared_from_this(); } + + private: // To enforce copy-on-write these are private and have read-only accessors typet t; @@ -198,9 +224,6 @@ class abstract_objectt:public std::enable_shared_from_this return internal_abstract_object_pointert(new abstract_objectt(*this)); } - virtual void update_sub_elements(const locationst &locations) - {} - abstract_object_pointert abstract_object_merge( const abstract_object_pointert other) const; diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index db3a4b30d0b..12513b80aeb 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -467,27 +467,29 @@ bool constant_array_abstract_objectt::eval_index( } } -/*******************************************************************\ - -Function: constant_array_abstract_objectt::update_sub_elements - - Inputs: - locations - Locations to write - - Outputs: None - - Purpose: Updates write location for sub-elements. - - For example, if a[2] = {5, 6}, this will update - the write location for objects 5 and 6 as well as a. - -\*******************************************************************/ - -void constant_array_abstract_objectt::update_sub_elements( - const locationst &locations) +/** + * Apply a visitor operation to all sub elements of this abstract_object. + * A sub element might be a member of a struct, or an element of an array, + * for instance, but this is entirely determined by the particular + * derived instance of abstract_objectt. + * + * \param visitor an instance of a visitor class that will be applied to + * all sub elements + * \return A new abstract_object if it's contents is modifed, or this if + * no modification is needed + */ +abstract_object_pointert +constant_array_abstract_objectt::visit_sub_elements( + const abstract_object_visitort &visitor) const { - for(auto &item: map) + const auto &result= + std::dynamic_pointer_cast( + mutable_clone()); + + for(auto &item : result->map) { - item.second=item.second->update_last_written_locations(locations, true); + item.second=visitor.visit(item.second); } + + return result; } diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index a0ffa8f8e1d..ce0fd6d7665 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -48,6 +48,9 @@ class constant_array_abstract_objectt:public array_abstract_objectt const abstract_object_pointert value, bool merging_write) const override; + virtual abstract_object_pointert visit_sub_elements( + const abstract_object_visitort &visitor) const override; + protected: CLONE @@ -85,8 +88,6 @@ class constant_array_abstract_objectt:public array_abstract_objectt abstract_object_pointert constant_array_merge( const constant_array_pointert other) const; - - virtual void update_sub_elements(const locationst &locations) override; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ARRAY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp b/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp index 7e243db8a2c..b364d133ea6 100644 --- a/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp @@ -30,24 +30,19 @@ void dependency_context_abstract_objectt::clear_top_internal() set_child(child_abstract_object->clear_top()); } -/*******************************************************************\ - -Function: dependency_context_abstract_objectt::update_last_written_locations - - Inputs: - Set of locations to be written. - - Outputs: - An abstract_object_pointer pointing to the cloned, updated object. - - Purpose: Creates a mutable clone of the current object, and updates - the last written location map with the provided location(s). - - For immutable objects. - -\*******************************************************************/ +/** + * Update the location context for an abstract object, potentially + * propogating the update to any children of this abstract object. + * + * \param locations the set of locations to be updated + * \param update_sub_elements if true, propogate the update operation to any + * children of this abstract object + * + * \return a clone of this abstract object with it's location context + * updated + */ abstract_object_pointert - dependency_context_abstract_objectt::update_last_written_locations( + dependency_context_abstract_objectt::update_location_context( const abstract_objectt::locationst &locations, const bool update_sub_elements) const { @@ -55,8 +50,14 @@ abstract_object_pointert std::dynamic_pointer_cast( mutable_clone()); - result->set_child(child_abstract_object->update_last_written_locations( - locations, update_sub_elements)); + if(update_sub_elements) + { + abstract_object_pointert visited_child= + child_abstract_object-> + update_location_context(locations, update_sub_elements)-> + visit_sub_elements(location_update_visitort(locations)); + result->set_child(visited_child); + } result->set_last_written_locations(locations); return result; @@ -224,7 +225,7 @@ abstract_object_pointert if(location_union.size()>get_last_written_locations().size()) { abstract_object_pointert result=mutable_clone(); - return result->update_last_written_locations(location_union, false); + return result->update_location_context(location_union, false); } } return shared_from_this(); @@ -300,8 +301,10 @@ abstract_objectt::locationst /** * Determine whether 'this' abstract_object has been modified in comparison * to a previous 'before' state. - * \param before The abstract_object_pointert to use as a reference to + * + * \param before the abstract_object_pointert to use as a reference to * compare against + * * \return true if 'this' is considered to have been modified in comparison * to 'before', false otherwise. */ @@ -334,7 +337,6 @@ bool dependency_context_abstract_objectt::has_been_modified( // For two sets of last written locations to match, // each location in one set must be equal to precisely one location // in the other, since a set can assume at most one match - const abstract_objectt::locationst &first_write_locations= before_context->get_last_written_locations(); const abstract_objectt::locationst &second_write_locations= diff --git a/src/analyses/variable-sensitivity/dependency_context_abstract_object.h b/src/analyses/variable-sensitivity/dependency_context_abstract_object.h index 1b095cf874e..aee64ad4095 100644 --- a/src/analyses/variable-sensitivity/dependency_context_abstract_object.h +++ b/src/analyses/variable-sensitivity/dependency_context_abstract_object.h @@ -64,10 +64,28 @@ class dependency_context_abstract_objectt: public abstract_objectt virtual bool has_been_modified(const abstract_object_pointert before) const override; - virtual abstract_object_pointert update_last_written_locations( + virtual abstract_object_pointert update_location_context( const abstract_objectt::locationst &locations, const bool update_sub_elements) const override; + // A visitor class to update the last_written_locations of any visited + // abstract_object with a given set of locations. + class location_update_visitort: + public abstract_objectt::abstract_object_visitort + { + public: + explicit location_update_visitort(const locationst &locations): + locations(locations) { } + + abstract_object_pointert visit(const abstract_object_pointert element) const + { + return element->update_location_context(locations, true); + } + + private: + const locationst &locations; + }; + locationst get_location_union(const locationst &locations) const; virtual const typet &type() const @@ -143,7 +161,6 @@ class dependency_context_abstract_objectt: public abstract_objectt void set_child( const abstract_object_pointert &child); - }; diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 0c7b7e57fa9..cbd76abd36f 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -386,27 +386,29 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( } } -/*******************************************************************\ - -Function: full_struct_abstract_objectt::update_sub_elements - - Inputs: - locations - Locations to write - - Outputs: None - - Purpose: Updates write location for sub-elements. - - For example, if a=b where a and b are structs, this will - update the write location for components too. - -\*******************************************************************/ - -void full_struct_abstract_objectt::update_sub_elements( - const locationst &locations) +/** + * Apply a visitor operation to all sub elements of this abstract_object. + * A sub element might be a member of a struct, or an element of an array, + * for instance, but this is entirely determined by the particular + * derived instance of abstract_objectt. + * + * \param visitor an instance of a visitor class that will be applied to + * all sub elements + * \return A new abstract_object if it's contents is modifed, or this if + * no modification is needed + */ +abstract_object_pointert + full_struct_abstract_objectt::visit_sub_elements( + const abstract_object_visitort &visitor) const { - for(auto &item: map) + const auto &result= + std::dynamic_pointer_cast( + mutable_clone()); + + for(auto &item : result->map) { - item.second=item.second->update_last_written_locations(locations, true); + item.second=visitor.visit(item.second); } + + return result; } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 8ad38081fbf..ae16b828069 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -36,6 +36,9 @@ class full_struct_abstract_objectt:public struct_abstract_objectt const class ai_baset &ai, const class namespacet &ns) const override; + virtual abstract_object_pointert visit_sub_elements( + const abstract_object_visitort &visitor) const override; + private: // no entry means component is top typedef std::map struct_mapt; @@ -61,8 +64,6 @@ class full_struct_abstract_objectt:public struct_abstract_objectt const abstract_object_pointert value, bool merging_write) const override; - virtual void update_sub_elements(const locationst &locations) override; - 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 diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 090f62e9308..14505418c75 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -55,8 +55,8 @@ void variable_sensitivity_domaint::transform( const abstract_objectt::locationst write_location={ from }; abstract_object_pointert top_object= abstract_state.abstract_object_factory( - to_code_decl(instruction.code).symbol().type(), ns, true) - ->update_last_written_locations(write_location, true); + to_code_decl(instruction.code).symbol().type(), ns, true) + ->update_location_context(write_location, true); abstract_state.assign( to_code_decl(instruction.code).symbol(), top_object, ns); } @@ -81,8 +81,8 @@ void variable_sensitivity_domaint::transform( const code_assignt &inst = to_code_assign(instruction.code); const abstract_objectt::locationst write_location={ from }; - abstract_object_pointert rhs = abstract_state.eval(inst.rhs(), ns) - ->update_last_written_locations(write_location, true); + abstract_object_pointert rhs =abstract_state.eval(inst.rhs(), ns) + ->update_location_context(write_location, true); abstract_state.assign(inst.lhs(), rhs, ns); } break; @@ -481,7 +481,8 @@ void variable_sensitivity_domaint::transform_function_call( // Evaluate the expression that is being // passed into the function call (called_arg) - abstract_object_pointert param_val=abstract_state.eval(called_arg, ns)->update_last_written_locations({ from }, true); + abstract_object_pointert param_val=abstract_state.eval(called_arg, ns) + ->update_location_context({from}, true); // Assign the evaluated value to the symbol associated with the // parameter of the function From 2b316b56d29cbc14905b3913f317bc7431d710ab Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 14 Feb 2018 13:32:02 +0000 Subject: [PATCH 187/342] Fixup variable-sensitivity unit tests to build after the giant rebase. --- .../abstract_object/merge.cpp | 2 +- .../constant_abstract_value/merge.cpp | 15 +- .../constant_array_abstract_object/merge.cpp | 23 +-- .../full_struct_abstract_object/merge.cpp | 23 +-- .../last_written_location.cpp | 179 +++++++++--------- .../variable-sensitivity/write_stack.cpp | 2 +- 6 files changed, 121 insertions(+), 123 deletions(-) diff --git a/unit/analyses/variable-sensitivity/abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp index aa33c9bfcf5..d11595a565a 100644 --- a/unit/analyses/variable-sensitivity/abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp @@ -6,7 +6,7 @@ \*******************************************************************/ -#include +#include #include #include diff --git a/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp index 3191ee9d132..0423411088e 100644 --- a/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp @@ -7,29 +7,24 @@ \*******************************************************************/ #include -#include +#include #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; -} - SCENARIO("merge_constant_abstract_value", "[core][analyses][variable-sensitivity][constant_abstract_value][merge]") { 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); + const exprt val1=from_integer(1, integer_typet()); + const exprt val2=from_integer(2, integer_typet()); abstract_environmentt enviroment; enviroment.make_top(); 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 b80ba724121..c3a51b50234 100644 --- a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp @@ -7,7 +7,7 @@ \*******************************************************************/ #include -#include +#include #include #include #include @@ -20,6 +20,7 @@ #include #include #include +#include typedef constant_array_abstract_objectt::constant_array_pointert constant_array_abstract_object_pointert; @@ -74,27 +75,27 @@ SCENARIO("merge_constant_array_abstract_object", GIVEN("Two arrays of size 3, whose first elements are the same") { const array_typet array_type( - integer_typet(), constant_exprt::integer_constant(3)); + integer_typet(), from_integer(3, integer_typet())); // 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)); + val1.operands().push_back(from_integer(1, integer_typet())); + val1.operands().push_back(from_integer(2, integer_typet())); + val1.operands().push_back(from_integer(3, integer_typet())); // 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)); + val2.operands().push_back(from_integer(1, integer_typet())); + val2.operands().push_back(from_integer(4, integer_typet())); + val2.operands().push_back(from_integer(5, integer_typet())); // index_exprt for reading from an array const index_exprt i0= - index_exprt(nil_exprt(), constant_exprt::integer_constant(0)); + index_exprt(nil_exprt(), from_integer(0, integer_typet())); const index_exprt i1= - index_exprt(nil_exprt(), constant_exprt::integer_constant(1)); + index_exprt(nil_exprt(), from_integer(1, integer_typet())); const index_exprt i2= - index_exprt(nil_exprt(), constant_exprt::integer_constant(2)); + index_exprt(nil_exprt(), from_integer(2, integer_typet())); abstract_environmentt enviroment; enviroment.make_top(); 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 e3c686c4663..a636eea0a9f 100644 --- a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp @@ -7,7 +7,7 @@ \*******************************************************************/ #include -#include +#include #include #include #include @@ -23,6 +23,7 @@ #include +#include typedef constant_array_abstract_objectt::constant_array_pointert constant_array_abstract_object_pointert; @@ -64,7 +65,7 @@ class struct_utilt enviroment, ns, std::stack(), - member_exprt(nil_exprt(), component.get_name()), + member_exprt(nil_exprt(), component.get_name(), component.type()), enviroment.eval(op, ns), false); result= @@ -112,20 +113,20 @@ SCENARIO("merge_full_struct_abstract_object", 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)); + val1.operands().push_back(from_integer(1, integer_typet())); + val1.operands().push_back(from_integer(2, integer_typet())); + val1.operands().push_back(from_integer(3, integer_typet())); // 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)); + val2.operands().push_back(from_integer(1, integer_typet())); + val2.operands().push_back(from_integer(4, integer_typet())); + val2.operands().push_back(from_integer(5, integer_typet())); // 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"); + const member_exprt a(nil_exprt(), "a", integer_typet()); + const member_exprt b(nil_exprt(), "b", integer_typet()); + const member_exprt c(nil_exprt(), "c", integer_typet()); abstract_environmentt enviroment; enviroment.make_top(); diff --git a/unit/analyses/variable-sensitivity/last_written_location.cpp b/unit/analyses/variable-sensitivity/last_written_location.cpp index ba28999bb41..3fba8c16c57 100644 --- a/unit/analyses/variable-sensitivity/last_written_location.cpp +++ b/unit/analyses/variable-sensitivity/last_written_location.cpp @@ -10,7 +10,7 @@ /// Unit tests for testing of correct tracking of /// last written location by objects -#include "catch.hpp" +#include #include #include @@ -23,104 +23,105 @@ #include #include #include +#include //#include SCENARIO("Constructing two environments to make sure we correctly identify modified symbols", "[core][analyses][variable-sensitivity][last-written-location]") { - GIVEN("Two identifiers that contain integer values") + GIVEN("Two identifiers that contain integer values") + { + const irep_idt identifier = "hello"; + auto first_val = symbol_exprt(identifier, integer_typet()); + symbolt first_sym; + first_sym.name = first_val.get_identifier(); + + auto rhs_val = from_integer(5, integer_typet()); + + const irep_idt second_identifier = "world"; + auto second_val = symbol_exprt(second_identifier, integer_typet()); + symbolt second_sym; + second_sym.name = second_val.get_identifier(); + + symbol_tablet symbol_table; + + symbol_table.add(first_sym); + symbol_table.add(second_sym); + namespacet ns(symbol_table); + + WHEN("The identifiers get inserted into two environments") { - const irep_idt identifier = "hello"; - auto first_val = symbol_exprt(identifier, integer_typet()); - symbolt first_sym; - first_sym.name = first_val.get_identifier(); - - auto rhs_val = constant_exprt::integer_constant(5); - - const irep_idt second_identifier = "world"; - auto second_val = symbol_exprt(second_identifier, integer_typet()); - symbolt second_sym; - second_sym.name = second_val.get_identifier(); - - symbol_tablet symbol_table; - - symbol_table.add(first_sym); - symbol_table.add(second_sym); - namespacet ns(symbol_table); - - WHEN("The identifiers get inserted into two environments") - { - abstract_environmentt env; - - auto first_eval_rhs = env.eval(rhs_val, ns); - auto first_eval_res = env.eval(first_val, ns); - - auto second_eval_res = env.eval(second_val, ns); - auto rhs_val_2 = constant_exprt::integer_constant(10); - auto second_eval_rhs = env.eval(rhs_val_2, ns); - - env.assign(first_val, first_eval_rhs, ns); - env.assign(second_val, second_eval_rhs, ns); - - abstract_environmentt second_env; - second_env.assign(first_val, first_eval_rhs, ns); - second_env.assign(second_val, second_eval_rhs, ns); - - THEN("The modified symbols between the two domains should be none") { - auto changed_vals = abstract_environmentt::modified_symbols( - env, second_env); - REQUIRE(changed_vals.size() == 0); - } + abstract_environmentt env; + + auto first_eval_rhs = env.eval(rhs_val, ns); + auto first_eval_res = env.eval(first_val, ns); + + auto second_eval_res = env.eval(second_val, ns); + auto rhs_val_2 = from_integer(10, integer_typet()); + auto second_eval_rhs = env.eval(rhs_val_2, ns); + + env.assign(first_val, first_eval_rhs, ns); + env.assign(second_val, second_eval_rhs, ns); + + abstract_environmentt second_env; + second_env.assign(first_val, first_eval_rhs, ns); + second_env.assign(second_val, second_eval_rhs, ns); + + THEN("The modified symbols between the two domains should be none") { + auto changed_vals = abstract_environmentt::modified_symbols( + env, second_env); + REQUIRE(changed_vals.size() == 0); } } - GIVEN("Two identifiers that contain integer values") + } + GIVEN("Two identifiers that contain integer values") + { + const irep_idt identifier = "hello"; + auto first_val = symbol_exprt(identifier, integer_typet()); + symbolt first_sym; + first_sym.name = first_val.get_identifier(); + + auto rhs_val = from_integer(5, integer_typet()); + + const irep_idt second_identifier = "world"; + auto second_val = symbol_exprt(second_identifier, integer_typet()); + symbolt second_sym; + second_sym.name = second_val.get_identifier(); + + symbol_tablet symbol_table; + + symbol_table.add(first_sym); + symbol_table.add(second_sym); + namespacet ns(symbol_table); + + WHEN("The identifiers get inserted into two environments, but one of \ + them has a different value in one of the environments") { - const irep_idt identifier = "hello"; - auto first_val = symbol_exprt(identifier, integer_typet()); - symbolt first_sym; - first_sym.name = first_val.get_identifier(); - - auto rhs_val = constant_exprt::integer_constant(5); - - const irep_idt second_identifier = "world"; - auto second_val = symbol_exprt(second_identifier, integer_typet()); - symbolt second_sym; - second_sym.name = second_val.get_identifier(); - - symbol_tablet symbol_table; - - symbol_table.add(first_sym); - symbol_table.add(second_sym); - namespacet ns(symbol_table); - - WHEN("The identifiers get inserted into two environments, but one of \ - them has a different value in one of the environments") - { - abstract_environmentt env; - - auto first_eval_rhs = env.eval(rhs_val, ns); - auto first_eval_res = env.eval(first_val, ns); - - auto second_eval_res = env.eval(second_val, ns); - auto rhs_val_2 = constant_exprt::integer_constant(10); - auto second_eval_rhs = env.eval(rhs_val_2, ns); - - env.assign(first_val, first_eval_rhs, ns); - env.assign(second_val, second_eval_rhs, ns); - - auto rhs_val_3 = constant_exprt::integer_constant(20); - - abstract_environmentt second_env; - auto new_rhs_val = second_env.eval(rhs_val_3, ns); - second_env.assign(first_val, first_eval_rhs, ns); - second_env.assign(second_val, new_rhs_val, ns); - - THEN("The modified symbols between the two domains should be none") { - auto changed_vals = abstract_environmentt::modified_symbols( - env, second_env); - REQUIRE(changed_vals.size() == 0); - } + abstract_environmentt env; + + auto first_eval_rhs = env.eval(rhs_val, ns); + auto first_eval_res = env.eval(first_val, ns); + + auto second_eval_res = env.eval(second_val, ns); + auto rhs_val_2 = from_integer(10, integer_typet()); + auto second_eval_rhs = env.eval(rhs_val_2, ns); + + env.assign(first_val, first_eval_rhs, ns); + env.assign(second_val, second_eval_rhs, ns); + + auto rhs_val_3 = from_integer(20, integer_typet()); + + abstract_environmentt second_env; + auto new_rhs_val = second_env.eval(rhs_val_3, ns); + second_env.assign(first_val, first_eval_rhs, ns); + second_env.assign(second_val, new_rhs_val, ns); + + THEN("The modified symbols between the two domains should be none") { + auto changed_vals = abstract_environmentt::modified_symbols( + env, second_env); + REQUIRE(changed_vals.size() == 0); } } + } } diff --git a/unit/analyses/variable-sensitivity/write_stack.cpp b/unit/analyses/variable-sensitivity/write_stack.cpp index 0ec3c9cd30b..116836bd70b 100644 --- a/unit/analyses/variable-sensitivity/write_stack.cpp +++ b/unit/analyses/variable-sensitivity/write_stack.cpp @@ -9,7 +9,7 @@ /// \file /// Unit tests for construction of write stack -#include "catch.hpp" +#include #include #include From e9bebead20aaf78227058fe282a3e0fcf9e46b73 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 13 Mar 2018 17:36:11 +0000 Subject: [PATCH 188/342] Convert assertions to invariants. --- .../abstract_enviroment.cpp | 14 ++++---- .../variable-sensitivity/abstract_object.cpp | 2 +- .../array_abstract_object.cpp | 6 ++-- .../constant_array_abstract_object.cpp | 6 ++-- .../constant_pointer_abstract_object.cpp | 8 ++--- .../full_struct_abstract_object.cpp | 32 +++++++++---------- .../pointer_abstract_object.cpp | 6 ++-- .../struct_abstract_object.cpp | 6 ++-- .../union_abstract_object.cpp | 6 ++-- .../variable_sensitivity_domain.cpp | 16 ++++++---- .../variable_sensitivity_object_factory.h | 2 +- 11 files changed, 53 insertions(+), 51 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index e1e28b69f8c..a2dabd21dab 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -159,7 +159,7 @@ Function: abstract_environmentt::assign bool abstract_environmentt::assign( const exprt &expr, const abstract_object_pointert value, const namespacet &ns) { - assert(value); + PRECONDITION(value); if(value->is_bottom()) { @@ -189,7 +189,7 @@ bool abstract_environmentt::assign( if(!lhs_value) { - assert(s.id()==ID_symbol); + INVARIANT(s.id()==ID_symbol, "Have a symbol or a stack"); const symbol_exprt &symbol_expr(to_symbol_expr(s)); if(map.find(symbol_expr)==map.end()) { @@ -230,7 +230,7 @@ bool abstract_environmentt::assign( 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); + INVARIANT(lhs_type==rhs_type, "Assignment types must match"); // If LHS was directly the symbol if(s.id()==ID_symbol) { @@ -276,7 +276,7 @@ abstract_object_pointert abstract_environmentt::write( const namespacet &ns, bool merge_write) { - assert(!remaining_stack.empty()); + PRECONDITION(!remaining_stack.empty()); const exprt & next_expr=remaining_stack.top(); remaining_stack.pop(); @@ -305,7 +305,7 @@ abstract_object_pointert abstract_environmentt::write( } else { - assert(0); + UNREACHABLE; return nullptr; } } @@ -332,7 +332,7 @@ bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) // 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); + PRECONDITION(expr.type().id()==ID_bool); // Evaluate the expression abstract_object_pointert res = eval(expr, ns); @@ -342,7 +342,7 @@ bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) if(possibly_constant.id()!=ID_nil) // I.E. actually a value { // Should be of the right type - assert(possibly_constant.type().id()==ID_bool); + INVARIANT(possibly_constant.type().id()==ID_bool, "simplication preserves type"); if(possibly_constant.is_false()) { diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 837daebf9a6..22ed7076910 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -54,7 +54,7 @@ Function: abstract_objectt::abstract_objectt abstract_objectt::abstract_objectt(const typet &type, bool top, bool bottom): t(type), bottom(bottom), top(top) { - assert(!(top && bottom)); + PRECONDITION(!(top && bottom)); } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 254457a369e..9b80ce5894b 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -28,7 +28,7 @@ Function: array_abstract_objectt::array_abstract_objectt array_abstract_objectt::array_abstract_objectt(const typet &t): abstract_objectt(t) { - assert(t.id()==ID_array); + PRECONDITION(t.id()==ID_array); } /*******************************************************************\ @@ -51,7 +51,7 @@ array_abstract_objectt::array_abstract_objectt( const typet &t, bool tp, bool bttm): abstract_objectt(t, tp, bttm) { - assert(t.id()==ID_array); + PRECONDITION(t.id()==ID_array); } /*******************************************************************\ @@ -75,7 +75,7 @@ array_abstract_objectt::array_abstract_objectt( const namespacet &ns): abstract_objectt(e, environment, ns) { - assert(e.type().id()==ID_array); + PRECONDITION(e.type().id()==ID_array); } /** diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 12513b80aeb..07b90027995 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -154,8 +154,8 @@ abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( result->map=merged_map; - assert(!result->is_top()); - assert(!result->is_bottom()); + INVARIANT(!result->is_top(), "merge of maps doesn't generate top"); + INVARIANT(!result->is_bottom(), "merge of maps doesn't generate bottom"); return result; } } @@ -277,7 +277,7 @@ abstract_object_pointert constant_array_abstract_objectt::read_index( } else { - assert(!is_bottom()); + PRECONDITION(!is_bottom()); mp_integer index_value; if(eval_index(index, env, ns, index_value)) { diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 7231774cb35..1a9db0ffa0d 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -31,7 +31,7 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( const typet &t): pointer_abstract_objectt(t) { - assert(t.id()==ID_pointer); + PRECONDITION(t.id()==ID_pointer); } /*******************************************************************\ @@ -54,7 +54,7 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( const typet &t, bool tp, bool bttm): pointer_abstract_objectt(t, tp, bttm) { - assert(t.id()==ID_pointer); + PRECONDITION(t.id()==ID_pointer); } /*******************************************************************\ @@ -95,7 +95,7 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( pointer_abstract_objectt(e, environment, ns), value_stack(e, environment, ns) { - assert(e.type().id()==ID_pointer); + PRECONDITION(e.type().id()==ID_pointer); if(value_stack.is_top_value()) { make_top(); @@ -328,7 +328,7 @@ sharing_ptrt if(stack.empty()) { // We should not be changing the type of an abstract object - assert(new_value->type()==type().subtype()); + PRECONDITION(new_value->type()==type().subtype()); // Get an expression that we can assign to exprt value=value_stack.to_expression().op0(); diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index cbd76abd36f..f542d60adac 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -36,8 +36,8 @@ Function: full_struct_abstract_objectt::struct_abstract_objectt full_struct_abstract_objectt::full_struct_abstract_objectt(const typet &t): struct_abstract_objectt(t) { - assert(t.id()==ID_struct); - assert(verify()); + PRECONDITION(t.id()==ID_struct); + DATA_INVARIANT(verify(), "Structural invariants maintained"); } /*******************************************************************\ @@ -60,8 +60,8 @@ 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); - assert(verify()); + PRECONDITION(t.id()==ID_struct); + DATA_INVARIANT(verify(), "Structural invariants maintained"); } /*******************************************************************\ @@ -84,7 +84,7 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( const namespacet &ns): struct_abstract_objectt(e, environment, ns) { - assert(verify()); + DATA_INVARIANT(verify(), "Structural invariants maintained"); } /*******************************************************************\ @@ -122,7 +122,7 @@ abstract_object_pointert full_struct_abstract_objectt::read_component( } else { - assert(!is_bottom()); + PRECONDITION(!is_bottom()); irep_idt c=member_expr.get_component_name(); @@ -203,7 +203,7 @@ sharing_ptrt copy->map[c]= environment.write(starting_value, value, stack, ns, merging_write); copy->clear_top(); - assert(copy->verify()); + DATA_INVARIANT(copy->verify(), "Structural invariants maintained");; return copy; } else @@ -219,11 +219,11 @@ sharing_ptrt { if(is_top()) // struct is top { - assert(copy->verify()); + DATA_INVARIANT(copy->verify(), "Structural invariants maintained");; return copy; } - assert(!copy->map.empty()); + INVARIANT(!copy->map.empty(), "If not top, map cannot be empty"); struct_mapt &m=copy->map; @@ -231,7 +231,7 @@ sharing_ptrt if(it==m.end()) // component is top { - assert(copy->verify()); + DATA_INVARIANT(copy->verify(), "Structural invariants maintained");; return copy; } @@ -243,10 +243,10 @@ sharing_ptrt { copy->map[c]=value; copy->clear_top(); - assert(!copy->is_bottom()); + INVARIANT(!copy->is_bottom(), "top != bottom"); } - assert(copy->verify()); + DATA_INVARIANT(copy->verify(), "Structural invariants maintained");; return copy; } } @@ -367,7 +367,7 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( abstract_objectt::merge_maps(map, other->map, merged_map); if(!modified) { - assert(verify()); + DATA_INVARIANT(verify(), "Structural invariants maintained"); return shared_from_this(); } else @@ -378,9 +378,9 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( result->map=merged_map; - assert(!result->is_top()); - assert(!result->is_bottom()); - assert(result->verify()); + INVARIANT(!result->is_top(), "Merge of maps will not generate top"); + INVARIANT(!result->is_bottom(), "Merge of maps will not generate bottom"); + DATA_INVARIANT(result->verify(), "Structural invariants maintained"); return result; } } diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index b02181f0f02..6d569f8693d 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -29,7 +29,7 @@ Function: pointer_abstract_objectt::pointer_abstract_objectt pointer_abstract_objectt::pointer_abstract_objectt(const typet &t): abstract_objectt(t) { - assert(t.id()==ID_pointer); + PRECONDITION(t.id()==ID_pointer); } /*******************************************************************\ @@ -52,7 +52,7 @@ pointer_abstract_objectt::pointer_abstract_objectt( const typet &t, bool tp, bool bttm): abstract_objectt(t, tp, bttm) { - assert(t.id()==ID_pointer); + PRECONDITION(t.id()==ID_pointer); } /*******************************************************************\ @@ -74,7 +74,7 @@ pointer_abstract_objectt::pointer_abstract_objectt( const namespacet &ns): abstract_objectt(e, environment, ns) { - assert(e.type().id()==ID_pointer); + PRECONDITION(e.type().id()==ID_pointer); } /** diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index d50199190c0..7c2364b64af 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -30,7 +30,7 @@ Function: struct_abstract_objectt::struct_abstract_objectt struct_abstract_objectt::struct_abstract_objectt(const typet &t): abstract_objectt(t) { - assert(t.id()==ID_struct); + PRECONDITION(t.id()==ID_struct); } /*******************************************************************\ @@ -53,7 +53,7 @@ struct_abstract_objectt::struct_abstract_objectt( const typet &t, bool tp, bool bttm): abstract_objectt(t, tp, bttm) { - assert(t.id()==ID_struct); + PRECONDITION(t.id()==ID_struct); } /*******************************************************************\ @@ -75,7 +75,7 @@ struct_abstract_objectt::struct_abstract_objectt( const namespacet &ns): abstract_objectt(e, environment, ns) { - assert(ns.follow(e.type()).id()==ID_struct); + PRECONDITION(ns.follow(e.type()).id()==ID_struct); } /** diff --git a/src/analyses/variable-sensitivity/union_abstract_object.cpp b/src/analyses/variable-sensitivity/union_abstract_object.cpp index ecf7a1054c9..37ce932b35f 100644 --- a/src/analyses/variable-sensitivity/union_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/union_abstract_object.cpp @@ -29,7 +29,7 @@ Function: union_abstract_objectt::union_abstract_objectt union_abstract_objectt::union_abstract_objectt(const typet &type): abstract_objectt(type) { - assert(type.id()==ID_union); + PRECONDITION(type.id()==ID_union); } /*******************************************************************\ @@ -52,7 +52,7 @@ union_abstract_objectt::union_abstract_objectt( const typet &type, bool top, bool bottom): abstract_objectt(type, top, bottom) { - assert(type.id()==ID_union); + PRECONDITION(type.id()==ID_union); } /*******************************************************************\ @@ -74,7 +74,7 @@ union_abstract_objectt::union_abstract_objectt( const namespacet &ns): abstract_objectt(expr, environment, ns) { - assert(ns.follow(expr.type()).id()==ID_union); + PRECONDITION(ns.follow(expr.type()).id()==ID_union); } /** diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 14505418c75..81378c46ee6 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -181,7 +181,7 @@ void variable_sensitivity_domaint::transform( throw "unrecognised instruction type"; } - assert(abstract_state.verify()); + DATA_INVARIANT(abstract_state.verify(), "Structural invariant"); } /*******************************************************************\ @@ -281,7 +281,7 @@ bool variable_sensitivity_domaint::merge( // Use the abstract_environment merge bool any_changes=abstract_state.merge(b.abstract_state); - assert(abstract_state.verify()); + DATA_INVARIANT(abstract_state.verify(), "Structural invariant"); return any_changes; } @@ -396,7 +396,7 @@ Function: variable_sensitivity_domaint::transform_function_call void variable_sensitivity_domaint::transform_function_call( locationt from, locationt to, ai_baset &ai, const namespacet &ns) { - assert(from->type==FUNCTION_CALL); + PRECONDITION(from->type==FUNCTION_CALL); const code_function_callt &function_call=to_code_function_call(from->code); const exprt &function=function_call.function(); @@ -434,7 +434,7 @@ void variable_sensitivity_domaint::transform_function_call( abstract_object_pointert pointer_value= abstract_state.eval(called_arg, ns); - assert(pointer_value); + CHECK_RETURN(pointer_value); // Write top to the pointer pointer_value->write( @@ -475,7 +475,7 @@ void variable_sensitivity_domaint::transform_function_call( { if(parameter_it==declaration_parameters.end()) { - assert(code_type.has_ellipsis()); + INVARIANT(code_type.has_ellipsis(), "Only case for insufficient args"); break; } @@ -494,12 +494,14 @@ void variable_sensitivity_domaint::transform_function_call( } // Too few arguments so invalid code - assert(parameter_it==declaration_parameters.end()); + DATA_INVARIANT( + parameter_it==declaration_parameters.end(), + "Number of arguments should match parameters"); } } else { - assert(to==next); + PRECONDITION(to==next); abstract_state.havoc("unknown opaque function call"); } } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index 71cb923a412..978c2c26f65 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -106,7 +106,7 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: } else { - assert(type==ns.follow(e.type())); + PRECONDITION(type==ns.follow(e.type())); return abstract_object_pointert( new abstract_object_classt(e, enviroment, ns)); } From dabc8e4dd007c3ccb54933eaeee8a99cfb673272 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 13 Mar 2018 17:53:51 +0000 Subject: [PATCH 189/342] Fix a crashing bug with type comparison. --- .../variable-sensitivity-bug-01/main.c | 14 ++++++++++++++ .../variable-sensitivity-bug-01/test.desc | 6 ++++++ .../constant_pointer_abstract_object.cpp | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 regression/goto-analyzer/variable-sensitivity-bug-01/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-bug-01/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-bug-01/main.c b/regression/goto-analyzer/variable-sensitivity-bug-01/main.c new file mode 100644 index 00000000000..4a41802bc39 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-bug-01/main.c @@ -0,0 +1,14 @@ +struct st { + int a; + int b; +}; + +struct st sts_inf; + +void func( struct st* inf); // no body + +void main(void) +{ + func(&sts_inf); // assertion failed here +} + diff --git a/regression/goto-analyzer/variable-sensitivity-bug-01/test.desc b/regression/goto-analyzer/variable-sensitivity-bug-01/test.desc new file mode 100644 index 00000000000..d9fef3799bc --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-bug-01/test.desc @@ -0,0 +1,6 @@ +CORE +main.c +--variable-sensitivity --structs --arrays --pointers --show +^EXIT=0$ +^SIGNAL=0$ +-- diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 1a9db0ffa0d..cb640b93b15 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -328,7 +328,7 @@ sharing_ptrt if(stack.empty()) { // We should not be changing the type of an abstract object - PRECONDITION(new_value->type()==type().subtype()); + PRECONDITION(new_value->type()==ns.follow(type().subtype())); // Get an expression that we can assign to exprt value=value_stack.to_expression().op0(); From ab1c8809276874b70049e7d1b0fc16dc805179b2 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Mon, 11 Dec 2017 11:29:19 +0000 Subject: [PATCH 190/342] Allows simplification of expressions containing non-const Previously, abstract_objectt::expression_transform returned top whenever one of the subexpressions of an operator was non-const, which didn't allow simplification in situations like int x = 0; int y = nondet_int(); int z = x * y; The old behavior would've replaced x * y with 0 * y, with this change it will correctly simplify it to 0 instead. --- .../simplify-complex-expression/main.c | 11 ++++++++ .../simplify-complex-expression/test.desc | 14 +++++++++++ .../simplify-multiply-by-zero/main.c | 8 ++++++ .../simplify-multiply-by-zero/test.desc | 11 ++++++++ .../variable-sensitivity/abstract_object.cpp | 25 ++++++++++++++----- 5 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 regression/goto-analyzer-simplify/simplify-complex-expression/main.c create mode 100644 regression/goto-analyzer-simplify/simplify-complex-expression/test.desc create mode 100644 regression/goto-analyzer-simplify/simplify-multiply-by-zero/main.c create mode 100644 regression/goto-analyzer-simplify/simplify-multiply-by-zero/test.desc diff --git a/regression/goto-analyzer-simplify/simplify-complex-expression/main.c b/regression/goto-analyzer-simplify/simplify-complex-expression/main.c new file mode 100644 index 00000000000..094de4b8134 --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-complex-expression/main.c @@ -0,0 +1,11 @@ +int nondet_int(void); + +int main(void) +{ + int r = nondet_int(); + r = r + 1; + if(r == 2) { + return 1; + } + return 0; +} diff --git a/regression/goto-analyzer-simplify/simplify-complex-expression/test.desc b/regression/goto-analyzer-simplify/simplify-complex-expression/test.desc new file mode 100644 index 00000000000..289cd7d363b --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-complex-expression/test.desc @@ -0,0 +1,14 @@ +CORE +main.c +--variable +r == 2 +^SIGNAL=0$ +^EXIT=6$ +-- +-- + +Checks for a bug that occurred while changing the simplifier, +where a variable would be replaced by the RHS of its last assignment, +even if the value of that expression had changed since then; +Most egregiously when the RHS contained the symbol on the LHS (thus leading +to a recursive definition). \ No newline at end of file diff --git a/regression/goto-analyzer-simplify/simplify-multiply-by-zero/main.c b/regression/goto-analyzer-simplify/simplify-multiply-by-zero/main.c new file mode 100644 index 00000000000..cdb243ad05c --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-multiply-by-zero/main.c @@ -0,0 +1,8 @@ +int nondet_int(void); + +int main(void) +{ + int K = nondet_int(); + int x = 0; + return K * x; +} diff --git a/regression/goto-analyzer-simplify/simplify-multiply-by-zero/test.desc b/regression/goto-analyzer-simplify/simplify-multiply-by-zero/test.desc new file mode 100644 index 00000000000..6262cbd7d01 --- /dev/null +++ b/regression/goto-analyzer-simplify/simplify-multiply-by-zero/test.desc @@ -0,0 +1,11 @@ +CORE +main.c +"--variable" +^SIGNAL=0$ +^EXIT=6$ +main#return_value = 0; +-- +-- +Tests that a multiplication +of variable*variable can be simplified +if one of the variables can be evaluated to 0. \ No newline at end of file diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 22ed7076910..ce62823732c 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -184,17 +184,18 @@ abstract_object_pointert abstract_objectt::expression_transform( { exprt constant_replaced_expr=expr; constant_replaced_expr.operands().clear(); + + // Two passes over the expression - one for simplification, + // another to check if there are any top subexpressions left for(const exprt &op : expr.operands()) { abstract_object_pointert lhs_abstract_object=environment.eval(op, ns); const exprt &lhs_value=lhs_abstract_object->to_constant(); - if(lhs_value.is_nil()) { - // 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 environment.abstract_object_factory(expr.type(), ns, true, false); + // do not give up if a sub-expression is not a constant, + // because the whole expression may still be simplified in some cases + constant_replaced_expr.operands().push_back(op); } else { @@ -204,7 +205,19 @@ abstract_object_pointert abstract_objectt::expression_transform( } } - exprt simplified=simplify_expr(constant_replaced_expr, ns); + exprt simplified = simplify_expr(constant_replaced_expr, ns); + + for(const exprt &op : simplified.operands()) + { + abstract_object_pointert lhs_abstract_object = environment.eval(op, ns); + const exprt &lhs_value = lhs_abstract_object->to_constant(); + if(lhs_value.is_nil()) + { + return environment.abstract_object_factory( + simplified.type(), ns, true, false); + } + } + return environment.abstract_object_factory(simplified.type(), simplified, ns); } From 5052882a2cbd29d3683ed971511d12f3d909dc29 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 13 Mar 2018 18:50:45 +0000 Subject: [PATCH 191/342] Test case for the evaluation of (false && x) in the variable sensitivity domain. --- .../main.c | 25 +++++++++++++++++++ .../test.desc | 10 ++++++++ 2 files changed, 35 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-annihiliator-test/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-annihiliator-test/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-annihiliator-test/main.c b/regression/goto-analyzer/variable-sensitivity-annihiliator-test/main.c new file mode 100644 index 00000000000..7881ba7ff30 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-annihiliator-test/main.c @@ -0,0 +1,25 @@ +extern int g_in1; +extern int g_in2; + +int g_out; + +void func(void); + +void main(void) +{ + g_in1 = 1; + + func(); +} + +void func(void) +{ + if (g_in1 == 0) + g_out = 1; // unreachable. + + if (g_in2 == 0) + g_out = 2; + + if (g_in1 == 0 && g_in2 == 0) + g_out = 3; // unreachable, but not . +} diff --git a/regression/goto-analyzer/variable-sensitivity-annihiliator-test/test.desc b/regression/goto-analyzer/variable-sensitivity-annihiliator-test/test.desc new file mode 100644 index 00000000000..4abfae4a5cb --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-annihiliator-test/test.desc @@ -0,0 +1,10 @@ +CORE +main.c +--variable-sensitivity --pointers --arrays --structs --unreachable-instructions +^EXIT=0$ +^SIGNAL=0$ +line 18 function func +g_out = 1; +line 24 function func +g_out = 3; +-- From 7ef217adfcde83c2ca62755e12cb3cb9109519c9 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 13 Mar 2018 18:04:05 +0000 Subject: [PATCH 192/342] Crashing test cases due to pointer arithmetic issues. --- .../variable-sensitivity-bug-02/main.c | 34 +++++++++++++++++++ .../variable-sensitivity-bug-02/test.desc | 6 ++++ .../variable-sensitivity-bug-03/main.c | 7 ++++ .../variable-sensitivity-bug-03/test.desc | 6 ++++ .../abstract_enviroment.cpp | 5 ++- 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 regression/goto-analyzer/variable-sensitivity-bug-02/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-bug-02/test.desc create mode 100644 regression/goto-analyzer/variable-sensitivity-bug-03/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-bug-03/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-bug-02/main.c b/regression/goto-analyzer/variable-sensitivity-bug-02/main.c new file mode 100644 index 00000000000..5867c127507 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-bug-02/main.c @@ -0,0 +1,34 @@ +// map.c +int map(int t_x, int * p_map) // mismatch :( +{ + int n = p_map[0]; + int *p_map_x = &p_map[1]; + int *p_map_y = p_map_x + n ; // assertion failed here + int i; + + if (t_x < p_map_x[0]) + return p_map_y[0]; + + for (i=1; itype()); // Write the value for the root symbol back into the map - INVARIANT(lhs_type==rhs_type, "Assignment types must match"); + INVARIANT(lhs_type==rhs_type, + "Assignment types must match" "\n" + "lhs_type :" + lhs_type.pretty() + "\n" + "rhs_type :" + rhs_type.pretty()); // If LHS was directly the symbol if(s.id()==ID_symbol) { From ba05bd52e371e74b34ab7d2a15b1842453da819e Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Tue, 13 Mar 2018 14:47:14 +0000 Subject: [PATCH 193/342] Use sharing_mapt instead of std::map in full_struct_abstract_object --- .../variable-sensitivity/abstract_object.h | 47 +++++- .../variable-sensitivity/abstract_value.cpp | 41 ++++++ .../full_struct_abstract_object.cpp | 137 +++++++++++------- .../full_struct_abstract_object.h | 9 +- 4 files changed, 180 insertions(+), 54 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 3c46cd7cb31..2606b63558c 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -35,6 +35,7 @@ #include #include +#include class typet; class constant_exprt; @@ -116,7 +117,12 @@ class abstract_objectt:public std::enable_shared_from_this std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; typedef std::set locationst; - + typedef sharing_mapt + shared_mapt; + + static void dump_map(std::ostream out, const shared_mapt &m); + static void dump_map_diff( + std::ostream out, const shared_mapt &m1, const shared_mapt &m2); abstract_object_pointert clone() const { @@ -194,7 +200,6 @@ class abstract_objectt:public std::enable_shared_from_this const abstract_object_visitort &visitor) const { return shared_from_this(); } - private: // To enforce copy-on-write these are private and have read-only accessors typet t; @@ -238,6 +243,15 @@ class abstract_objectt:public std::enable_shared_from_this const std::map &map2, std::map &out_map); + + template + static bool merge_shared_maps( + const sharing_mapt &map1, + const sharing_mapt &map2, + sharing_mapt &out_map); + + + // The one exception is merge in descendant classes, which needs this void make_top() { top=true; this->make_top_internal(); } void clear_top() { top=false; this->clear_top_internal(); } @@ -288,5 +302,34 @@ bool abstract_objectt::merge_maps( return modified; } +template +bool abstract_objectt::merge_shared_maps( + const sharing_mapt &m1, + const sharing_mapt &m2, + sharing_mapt &out_map) +{ + typedef sharing_mapt + abstract_object_mapt; + + bool modified=false; + + abstract_object_mapt::delta_viewt delta_view; + m1.get_delta_view(m2, delta_view, true); + + for(auto &item : delta_view) + { + bool changes = false; + abstract_object_pointert v_new = abstract_objectt::merge( + item.m, item.other_m, changes); + if (changes) + { + modified = true; + out_map[item.k] = v_new; + } + } + + return modified; +} #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/abstract_value.cpp b/src/analyses/variable-sensitivity/abstract_value.cpp index 6a2f75a8c55..1990d224b5a 100644 --- a/src/analyses/variable-sensitivity/abstract_value.cpp +++ b/src/analyses/variable-sensitivity/abstract_value.cpp @@ -71,3 +71,44 @@ abstract_valuet::abstract_valuet( const namespacet &ns): abstract_objectt(expr, environment, ns) {} + + +void abstract_objectt::dump_map( + std::ostream out, const abstract_objectt::shared_mapt &m) +{ + shared_mapt::viewt view; + m.get_view(view); + + out << "{"; + bool first=true; + for(auto &item : view) + { + out << (first ? "" : ", ") << item.first; + first = false; + } + out << "}"; +} + +/** + * \brief Dump all elements in m1 that are different or missing in m2 + * + * \param m1 the 'target' sharing_map + * \param m2 the reference sharing map + */ +void abstract_objectt::dump_map_diff( + std::ostream out, + const abstract_objectt::shared_mapt &m1, + const abstract_objectt::shared_mapt &m2) +{ + shared_mapt::delta_viewt delta_view; + m1.get_delta_view(m2, delta_view, false); + + out << "DELTA{"; + bool first = true; + for(auto &item : delta_view) + { + out << (first ? "" : ", ") << item.k << "=" << item.in_both; + first = false; + } + out << "}"; +} diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index f542d60adac..d3d878206a3 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -20,6 +20,18 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com #include #endif +/** + * \brief Explicit copy-constructor to make it clear that the shared_map + * used to store the values of fields is copy-constructed as well + * to ensure it shares as much data as possible. + */ +full_struct_abstract_objectt::full_struct_abstract_objectt( + const full_struct_abstract_objectt &ao): + struct_abstract_objectt(ao), map(ao.map) +{ + DATA_INVARIANT(verify(), "Structural invariants maintained"); +} + /*******************************************************************\ Function: full_struct_abstract_objectt::struct_abstract_objectt @@ -124,13 +136,13 @@ abstract_object_pointert full_struct_abstract_objectt::read_component( { PRECONDITION(!is_bottom()); - irep_idt c=member_expr.get_component_name(); + const irep_idt c=member_expr.get_component_name(); - struct_mapt::const_iterator it=map.find(c); + shared_struct_mapt::const_find_type value=map.find(c); - if(it!=map.cend()) + if(value.second) { - return it->second; + return value.first; } else { @@ -182,14 +194,15 @@ sharing_ptrt member_expr.compound().type(), false, true)); } - internal_sharing_ptrt copy( - new full_struct_abstract_objectt(*this)); + const auto &result= + std::dynamic_pointer_cast(mutable_clone()); if(!stack.empty()) { abstract_object_pointert starting_value; - irep_idt c=member_expr.get_component_name(); - if(map.find(c)==map.cend()) + const irep_idt c=member_expr.get_component_name(); + shared_struct_mapt::const_find_type old_value = map.find(c); + if(!old_value.second) { starting_value= environment.abstract_object_factory( @@ -197,14 +210,15 @@ sharing_ptrt } else { - starting_value=map.at(c); + starting_value=old_value.first; } - copy->map[c]= + result->map[c] = environment.write(starting_value, value, stack, ns, merging_write); - copy->clear_top(); - DATA_INVARIANT(copy->verify(), "Structural invariants maintained");; - return copy; + + result->clear_top(); + DATA_INVARIANT(result->verify(), "Structural invariants maintained"); + return result; } else { @@ -213,41 +227,40 @@ sharing_ptrt std::cout << "Setting component" << std::endl; #endif - irep_idt c=member_expr.get_component_name(); + const irep_idt c=member_expr.get_component_name(); if(merging_write) { if(is_top()) // struct is top { - DATA_INVARIANT(copy->verify(), "Structural invariants maintained");; - return copy; + DATA_INVARIANT(result->verify(), "Structural invariants maintained"); + return result; } - INVARIANT(!copy->map.empty(), "If not top, map cannot be empty"); + INVARIANT(!result->map.empty(), "If not top, map cannot be empty"); - struct_mapt &m=copy->map; + shared_struct_mapt::const_find_type old_value=result->map.find(c); - struct_mapt::iterator it=m.find(c); - - if(it==m.end()) // component is top + if(!old_value.second) // component is top { - DATA_INVARIANT(copy->verify(), "Structural invariants maintained");; - return copy; + DATA_INVARIANT(result->verify(), "Structural invariants maintained"); + return result; } bool dummy; - it->second=abstract_objectt::merge(it->second, value, dummy); + result->map[c] = abstract_objectt::merge(old_value.first, value, dummy); } else { - copy->map[c]=value; - copy->clear_top(); - INVARIANT(!copy->is_bottom(), "top != bottom"); + result->map[c] = value; + result->clear_top(); + INVARIANT(!result->is_bottom(), "top != bottom"); } - DATA_INVARIANT(copy->verify(), "Structural invariants maintained");; - return copy; + DATA_INVARIANT(result->verify(), "Structural invariants maintained"); + + return result; } } @@ -272,15 +285,27 @@ Function: full_struct_abstract_objectt::output void full_struct_abstract_objectt::output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const { + // To ensure that a consistent ordering of fields is output, use + // the underlying type declaration for this struct to determine + // the ordering + struct_union_typet type_decl = to_struct_union_type(ns.follow(type())); + + bool first = true; + out << "{"; - for(const auto &entry : map) + for(const auto field : type_decl.components()) { - if(entry.first!=map.cbegin()->first) + auto value = map.find(field.get_name()); + if(value.second) { - out << ", "; + if(!first) + { + out << ", "; + } + out << '.' << field.get_name() << '='; + value.first->output(out, ai, ns); + first = false; } - out << "." << entry.first << "="; - entry.second->output(out, ai, ns); } out << "}"; } @@ -362,9 +387,12 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( } else { - struct_mapt merged_map; - bool modified= - abstract_objectt::merge_maps(map, other->map, merged_map); + const auto &result= + std::dynamic_pointer_cast(mutable_clone()); + + bool modified = abstract_objectt::merge_shared_maps( + map, other->map, result->map); + if(!modified) { DATA_INVARIANT(verify(), "Structural invariants maintained"); @@ -372,12 +400,6 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( } else { - const auto &result= - std::dynamic_pointer_cast( - mutable_clone()); - - result->map=merged_map; - INVARIANT(!result->is_top(), "Merge of maps will not generate top"); INVARIANT(!result->is_bottom(), "Merge of maps will not generate bottom"); DATA_INVARIANT(result->verify(), "Structural invariants maintained"); @@ -397,18 +419,33 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( * \return A new abstract_object if it's contents is modifed, or this if * no modification is needed */ -abstract_object_pointert - full_struct_abstract_objectt::visit_sub_elements( +abstract_object_pointert full_struct_abstract_objectt::visit_sub_elements( const abstract_object_visitort &visitor) const { const auto &result= - std::dynamic_pointer_cast( - mutable_clone()); + std::dynamic_pointer_cast(mutable_clone()); + + bool modified = false; + + shared_struct_mapt::viewt view; + result->map.get_view(view); - for(auto &item : result->map) + for(auto &item : view) { - item.second=visitor.visit(item.second); + auto newval = visitor.visit(item.second); + if(newval != item.second) + { + result->map[item.first] = visitor.visit(item.second); + modified = true; + } } - return result; + if(modified) + { + return result; + } + else + { + return shared_from_this(); + } } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index ae16b828069..604a5f78688 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -13,6 +13,7 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com #include #include #include +#include class abstract_environmentt; class member_exprt; @@ -22,6 +23,9 @@ class full_struct_abstract_objectt:public struct_abstract_objectt public: typedef sharing_ptrt constant_struct_pointert; + // Define an explicit copy constructor to ensure sharing of maps + full_struct_abstract_objectt(const full_struct_abstract_objectt &ao); + explicit full_struct_abstract_objectt(const typet &type); full_struct_abstract_objectt(const typet &type, bool top, bool bottom); @@ -41,8 +45,9 @@ class full_struct_abstract_objectt:public struct_abstract_objectt private: // no entry means component is top - typedef std::map struct_mapt; - struct_mapt map; + typedef sharing_mapt + shared_struct_mapt; + shared_struct_mapt map; abstract_object_pointert merge_constant_structs( constant_struct_pointert other) const; From f09fa4b1d1f106cd9474b123b1adef04727f7e2b Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 14 Mar 2018 11:32:43 +0000 Subject: [PATCH 194/342] Use sharing_mapt for abstract environment --- .../abstract_enviroment.cpp | 32 +++++++++---------- .../abstract_enviroment.h | 3 +- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index b0e54c44ec9..06798121bee 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -52,14 +52,14 @@ abstract_object_pointert abstract_environmentt::eval( 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()) + const auto &symbol_entry=map.find(symbol.get_identifier()); + if(!symbol_entry.has_value()) { return abstract_object_factory(simplified_expr.type(), ns, true); } else { - abstract_object_pointert found_symbol_value=symbol_entry->second; + abstract_object_pointert found_symbol_value=symbol_entry.value(); return found_symbol_value; } } @@ -191,7 +191,7 @@ bool abstract_environmentt::assign( { INVARIANT(s.id()==ID_symbol, "Have a symbol or a stack"); const symbol_exprt &symbol_expr(to_symbol_expr(s)); - if(map.find(symbol_expr)==map.end()) + if(!map.has_key(symbol_expr.get_identifier())) { lhs_value=abstract_object_factory( symbol_expr.type(), ns, true, false); @@ -486,9 +486,9 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) // 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) + for(const auto &entry : env.map.get_view()) { - if(map.find(entry.first)!=map.end()) + if(map.has_key(entry.first)) { bool object_modified=false; abstract_object_pointert new_object= @@ -629,10 +629,10 @@ void abstract_environmentt::output( { out << "{\n"; - for(const auto &entry : map) + for(const auto &entry : map.get_view()) { out << entry.first.get_identifier() - << " (" << ") -> "; + << " () -> "; entry.second->output(out, ai, ns); out << "\n"; } @@ -653,9 +653,9 @@ Function: abstract_environmentt::verify bool abstract_environmentt::verify() const { - for(const auto &entry : map) + for(const auto &entry : map.get_view()) { - if(!entry.second) + if(entry.second == nullptr) { return false; } @@ -715,21 +715,21 @@ std::vector abstract_environmentt::modified_symbols( { // Find all symbols who have different write locations in each map std::vector symbols_diff; - for (const auto &entry : first.map) + for (const auto &entry : first.map.get_view()) { - const auto &second_entry = second.map.find(entry.first); - if (second_entry != second.map.end()) + const auto second_entry = second.map.const_find(entry.first); + if (second_entry.second) { - if(second_entry->second->has_been_modified(entry.second)) + if(second_entry.first->has_been_modified(entry.second)) symbols_diff.push_back(entry.first); } } // Add any symbols that are only in the second map - for(const auto &entry : second.map) + for(const auto &entry : second.map.get_view()) { const auto &second_entry = first.map.find(entry.first); - if (second_entry==first.map.end()) + if (!second_entry.second) { symbols_diff.push_back(entry.first); } diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 41ec22644c7..f41480e1390 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -18,6 +18,7 @@ #include #include #include +#include class abstract_environmentt { @@ -80,7 +81,7 @@ class abstract_environmentt const exprt &e, const namespacet &ns) const; typedef symbol_exprt map_keyt; - std::map map; + sharing_mapt map; private: abstract_object_pointert abstract_object_factory( From 96ebc783be9e082f5af34f38eb5d70bfb689c0a8 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Mon, 19 Mar 2018 16:10:49 +0000 Subject: [PATCH 195/342] Fix a silly double call of visitor.visit() in full_struct_abstract_objectt --- .../variable-sensitivity/full_struct_abstract_object.cpp | 2 +- 1 file changed, 1 insertion(+), 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 d3d878206a3..21e971ae228 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -435,7 +435,7 @@ abstract_object_pointert full_struct_abstract_objectt::visit_sub_elements( auto newval = visitor.visit(item.second); if(newval != item.second) { - result->map[item.first] = visitor.visit(item.second); + result->map[item.first] = newval; modified = true; } } From 71b99c4cbee92732efcac56e6ead27a28a2c47cb Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Sun, 18 Mar 2018 16:02:41 +0000 Subject: [PATCH 196/342] Use sharing_mapt in constant_array_abstract_objectt --- .../variable-sensitivity/abstract_object.h | 23 +++--- .../constant_array_abstract_object.cpp | 71 +++++++++++++------ .../constant_array_abstract_object.h | 11 ++- 3 files changed, 67 insertions(+), 38 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 2606b63558c..3fe561bb7fb 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -244,11 +244,11 @@ class abstract_objectt:public std::enable_shared_from_this std::map &out_map); - template + template static bool merge_shared_maps( - const sharing_mapt &map1, - const sharing_mapt &map2, - sharing_mapt &out_map); + const sharing_mapt &map1, + const sharing_mapt &map2, + sharing_mapt &out_map); @@ -302,20 +302,15 @@ bool abstract_objectt::merge_maps( return modified; } -template +template bool abstract_objectt::merge_shared_maps( - const sharing_mapt &m1, - const sharing_mapt &m2, - sharing_mapt &out_map) + const sharing_mapt &m1, + const sharing_mapt &m2, + sharing_mapt &out_map) { - typedef sharing_mapt - abstract_object_mapt; - bool modified=false; - abstract_object_mapt::delta_viewt delta_view; - m1.get_delta_view(m2, delta_view, true); + auto delta_view = m1.get_delta_view(m2, true); for(auto &item : delta_view) { diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 07b90027995..cea6b00aad6 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -139,9 +139,9 @@ abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( } else { - array_mapt merged_map=array_mapt(); + shared_array_mapt merged_map(map); bool modified= - abstract_objectt::merge_maps(map, other->map, merged_map); + abstract_objectt::merge_shared_maps(map, other->map, merged_map); if(!modified) { return shared_from_this(); @@ -188,8 +188,11 @@ void constant_array_abstract_objectt::output( } else { + shared_array_mapt::sorted_viewt view; + map.get_view(view); + out << "{"; - for(const auto &entry : map) + for(const auto &entry : view) { out << "[" << entry.first << "] = "; entry.second->output(out, ai, ns); @@ -281,14 +284,16 @@ abstract_object_pointert constant_array_abstract_objectt::read_index( mp_integer index_value; if(eval_index(index, env, ns, index_value)) { + shared_array_mapt::const_find_type value = map.find(index_value); + // Here we are assuming it is always in bounds - if(map.find(index_value)==map.cend()) + if(!value.second) { return env.abstract_object_factory(type().subtype(), ns, true, false); } else { - return map.find(index_value)->second; + return value.first; } } else @@ -339,7 +344,7 @@ sharing_ptrt { if(stack.empty()) { - auto copy= + auto result= internal_sharing_ptrt( new constant_array_abstract_objectt(*this)); @@ -348,11 +353,11 @@ sharing_ptrt { if(is_top()) { - copy->clear_top(); + result->clear_top(); } - copy->map[index_value]=value; - return copy; + result->map[index_value]=value; + return result; } else { @@ -364,7 +369,7 @@ sharing_ptrt } else { - auto copy= + auto result= internal_sharing_ptrt( new constant_array_abstract_objectt(*this)); @@ -373,9 +378,11 @@ sharing_ptrt { // Here we assume the write is in bounds abstract_object_pointert array_entry; - if(map.find(index_value)!=map.cend()) + shared_array_mapt::const_find_type old_value = map.find(index_value); + + if(old_value.second) { - array_entry=map.at(index_value); + array_entry=old_value.first; } else { @@ -384,28 +391,31 @@ sharing_ptrt if(is_top()) { - copy->clear_top(); + result->clear_top(); } - copy->map[index_value]=environment.write( + result->map[index_value]=environment.write( array_entry, value, stack, ns, merging_write); - return copy; + return result; } else { - for(const auto &array_entry : map) + shared_array_mapt::viewt view; + map.get_view(view); + + for(const auto &array_entry : view) { // Merging write since we don't know which index we are writing to - copy->map[array_entry.first]= + result->map[array_entry.first]= environment.write( array_entry.second, value, stack, ns, true); if(is_top()) { - copy->clear_top(); + result->clear_top(); } } - return copy; + return result; } } } @@ -486,10 +496,27 @@ constant_array_abstract_objectt::visit_sub_elements( std::dynamic_pointer_cast( mutable_clone()); - for(auto &item : result->map) + bool modified = false; + + shared_array_mapt::viewt view; + result->map.get_view(view); + + for(auto &item : view) { - item.second=visitor.visit(item.second); + auto newval = visitor.visit(item.second); + if(newval != item.second) + { + result->map[item.first]=newval; + modified = true; + } } - return result; + if(modified) + { + return result; + } + else + { + return shared_from_this(); + } } diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index ce0fd6d7665..57723c9efbf 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -74,8 +74,15 @@ class constant_array_abstract_objectt:public array_abstract_objectt // 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; + struct mp_integer_hash + { + size_t operator()(const mp_integer &i) const { return std::hash{}(i.to_ulong()); } + }; + + typedef sharing_mapt + shared_array_mapt; + + shared_array_mapt map; bool eval_index( const index_exprt &index, From cb5fdf231d4e43fe40ce5cb0f71d0b60fa9fd9b2 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 19 Mar 2018 18:30:10 +0000 Subject: [PATCH 197/342] Remove deprecated call to negate. --- src/analyses/variable-sensitivity/write_stack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/write_stack.cpp b/src/analyses/variable-sensitivity/write_stack.cpp index 1d4b69b1917..54c89b38115 100644 --- a/src/analyses/variable-sensitivity/write_stack.cpp +++ b/src/analyses/variable-sensitivity/write_stack.cpp @@ -85,7 +85,7 @@ void write_stackt::construct_stack_to_pointer( top_stack=true; return; } - offset.negate(); + offset = unary_minus_exprt(offset); } abstract_object_pointert offset_value=environment.eval(offset, ns); From fb670adfba8eb93f940f654658508a8aebce7ca6 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Tue, 20 Mar 2018 15:23:23 +0000 Subject: [PATCH 198/342] Avoid unnecessarily breaking sharing --- .../abstract_enviroment.cpp | 37 ++++++------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 06798121bee..667630067c2 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -198,7 +198,7 @@ bool abstract_environmentt::assign( } else { - lhs_value=map[symbol_expr]; + lhs_value=map.const_find(symbol_expr).first; } } @@ -239,7 +239,7 @@ bool abstract_environmentt::assign( { symbol_exprt symbol_expr=to_symbol_expr(s); - if(final_value != map[symbol_expr]) + if(final_value != lhs_value) { map[symbol_expr]=final_value; } @@ -486,33 +486,18 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) // 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.get_view()) + for(const auto &entry : env.map.get_delta_view(map)) { - if(map.has_key(entry.first)) - { - bool object_modified=false; - abstract_object_pointert new_object= - abstract_objectt::merge( - map[entry.first], - entry.second, - object_modified); - - modified|=object_modified; - map[entry.first]=new_object; - - // Write, even if TOP. Since we now track the write locations of an - // object, even if it is TOP we still have useful information about it. - // This is used for when we want to find out what has been modified - // between two locations (even if we don't know what has been written). - } - else - { - // Map doesn't contain key so the resulting map shouldn't either - } + bool object_modified=false; + abstract_object_pointert new_object= + abstract_objectt::merge( + entry.other_m, + entry.m, + object_modified); + modified|=object_modified; + map.find(entry.k, tvt(true)).first=new_object; } - // Keep TOP items too. - return modified; } } From e5c1aa4f116ea939f532c213372be705b4df014b Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 18 Apr 2018 11:37:18 +0100 Subject: [PATCH 199/342] CLEANUP: Correct indentation --- src/analyses/variable-sensitivity/abstract_object.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 3fe561bb7fb..aa77d17a508 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -138,12 +138,12 @@ class abstract_objectt:public std::enable_shared_from_this * to 'before', false otherwise. */ virtual bool has_been_modified(const abstract_object_pointert before) const - { - // Default implementation, with no other information to go on - // falls back to relying on copy-on-write and pointer inequality - // to indicate if an abstract_objectt has been modified - return this != before.get(); - }; + { + // Default implementation, with no other information to go on + // falls back to relying on copy-on-write and pointer inequality + // to indicate if an abstract_objectt has been modified + return this != before.get(); + }; static abstract_object_pointert merge( abstract_object_pointert op1, From 95a8744b3aaa22887199a51caf8cc4aa0e54625f Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Thu, 19 Apr 2018 16:06:12 +0100 Subject: [PATCH 200/342] CLEANUP: Remove unneeded include of full_struct_abstract_object.h --- .../variable-sensitivity/dependency_context_abstract_object.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp b/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp index b364d133ea6..6d3fd85d032 100644 --- a/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp @@ -10,7 +10,6 @@ #include #include #include "dependency_context_abstract_object.h" -#include "full_struct_abstract_object.h" void dependency_context_abstract_objectt::set_child( const abstract_object_pointert &child) From 987f6dbf111a160ef3c9d3971ee51c93eed7f156 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Thu, 19 Apr 2018 16:08:59 +0100 Subject: [PATCH 201/342] CLEANUP: Correct authorship of dependency_context_abstract_object --- .../variable-sensitivity/dependency_context_abstract_object.cpp | 2 +- .../variable-sensitivity/dependency_context_abstract_object.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp b/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp index 6d3fd85d032..a34bd0044fb 100644 --- a/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp @@ -2,7 +2,7 @@ Module: analyses variable-sensitivity - Author: Chris Ryder, chris.ryder@diffblue.com + Author: Diffblue Ltd. \*******************************************************************/ diff --git a/src/analyses/variable-sensitivity/dependency_context_abstract_object.h b/src/analyses/variable-sensitivity/dependency_context_abstract_object.h index aee64ad4095..ccb7ebc202b 100644 --- a/src/analyses/variable-sensitivity/dependency_context_abstract_object.h +++ b/src/analyses/variable-sensitivity/dependency_context_abstract_object.h @@ -2,7 +2,7 @@ Module: analyses variable-sensitivity - Author: Chris Ryder, chris.ryder@diffblue.com + Author: Diffblue Ltd. \*******************************************************************/ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_DEPENDENCY_CONTEXT_ABSTRACT_OBJECT_H From 224c6dc5edafb2db5c4c45a0b772971418388bcf Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Tue, 24 Apr 2018 14:01:42 +0100 Subject: [PATCH 202/342] CLEANUP: Make constant_array_abstract_object match full_struct_abstract_object Both constant_array_abstract_object and full_struct_abstract_object have similar logic to handle their additional sensitivity over their base classes (array_abstract_object and struct_abstract_object) but their two implementation code layouts have diverged quite a bit. This patch makes the two implementations have a much closer layout to each other, which helps with comparing the two implementations when debugging. --- .../array_abstract_object.cpp | 4 +- .../array_abstract_object.h | 4 +- .../constant_array_abstract_object.cpp | 222 +++++++++--------- .../constant_array_abstract_object.h | 23 +- 4 files changed, 119 insertions(+), 134 deletions(-) diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 9b80ce5894b..e8a3c7c4560 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -95,7 +95,7 @@ abstract_object_pointert array_abstract_objectt::read( const exprt &specifier, const namespacet &ns) const { - return read_index(env, to_index_expr(specifier), ns); + return this->read_index(env, to_index_expr(specifier), ns); } /** @@ -122,7 +122,7 @@ abstract_object_pointert array_abstract_objectt::write( const abstract_object_pointert value, bool merging_write) const { - return write_index( + return this->write_index( environment, ns, stack, to_index_expr(specifier), value, merging_write); } diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index abee425aace..aaeb6c885ed 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -42,12 +42,12 @@ class array_abstract_objectt:public abstract_objectt protected: CLONE - abstract_object_pointert read_index( + virtual abstract_object_pointert read_index( const abstract_environmentt &env, const index_exprt &index, const namespacet &ns) const; - sharing_ptrt write_index( + virtual sharing_ptrt write_index( abstract_environmentt &environment, const namespacet &ns, const std::stack stack, diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index cea6b00aad6..bb365371129 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -29,7 +29,9 @@ Function: constant_array_abstract_objectt::constant_array_abstract_objectt constant_array_abstract_objectt::constant_array_abstract_objectt(typet type): array_abstract_objectt(type) -{} +{ + DATA_INVARIANT(verify(), "Structural invariants maintained"); +} /*******************************************************************\ @@ -50,7 +52,9 @@ Function: constant_array_abstract_objectt::constant_array_abstract_objectt constant_array_abstract_objectt::constant_array_abstract_objectt( typet type, bool top, bool bottom): array_abstract_objectt(type, top, bottom) -{} +{ + DATA_INVARIANT(verify(), "Structural invariants maintained"); +} /*******************************************************************\ @@ -83,6 +87,29 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( } clear_top(); } + DATA_INVARIANT(verify(), "Structural invariants maintained"); +} + +/*******************************************************************\ + +Function: constant_array_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 constant_array_abstract_objectt::verify() const +{ + // 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(); } /*******************************************************************\ @@ -139,23 +166,23 @@ abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( } else { - shared_array_mapt merged_map(map); - bool modified= - abstract_objectt::merge_shared_maps(map, other->map, merged_map); + const auto &result= + std::dynamic_pointer_cast(mutable_clone()); + + bool modified = + abstract_objectt::merge_shared_maps( + map, other->map, result->map); + if(!modified) { + DATA_INVARIANT(verify(), "Structural invariants maintained"); return shared_from_this(); } else { - const auto &result= - std::dynamic_pointer_cast( - mutable_clone()); - - result->map=merged_map; - - INVARIANT(!result->is_top(), "merge of maps doesn't generate top"); - INVARIANT(!result->is_bottom(), "merge of maps doesn't generate bottom"); + INVARIANT(!result->is_top(), "Merge of maps will not generate top"); + INVARIANT(!result->is_bottom(), "Merge of maps will not generate bottom"); + DATA_INVARIANT(result->verify(), "Structural invariants maintained"); return result; } } @@ -202,55 +229,6 @@ void constant_array_abstract_objectt::output( } } -/** - * A helper function to evaluate an abstract object contained - * within a container object. More precise abstractions may override this - * to return more precise results. - * - * \param env the abstract environment - * \param specifier a modifier expression, such as an array index or field - * specifier used to indicate access to a specific component - * \param ns the current namespace - * - * \return the abstract_objectt representing the value of the read component. - */ -abstract_object_pointert constant_array_abstract_objectt::read( - const abstract_environmentt &env, - const exprt &specifier, - const namespacet &ns) const -{ - return read_index(env, to_index_expr(specifier), ns); -} - -/** - * A helper function to evaluate writing to a component of an - * abstract object. More precise abstractions may override this to - * update what they are storing for a specific component. - * - * \param environment the abstract environment - * \param ns the current namespace - * \param stack the remaining stack of expressions on the LHS to evaluate - * \param specifier the expression uses to access a specific component - * \param value the value we are trying to write to the component - * \param merging_write if true, this and all future writes will be merged - * with the current value - * - * \return the abstract_objectt representing the result of writing - * to a specific component. - */ -abstract_object_pointert constant_array_abstract_objectt::write( - abstract_environmentt &environment, - const namespacet &ns, - const std::stack stack, - const exprt &specifier, - const abstract_object_pointert value, - bool merging_write) const -{ - return write_index( - environment, ns, stack, to_index_expr(specifier), value, - merging_write); -} - /*******************************************************************\ Function: constant_array_abstract_objectt::read_index @@ -340,84 +318,102 @@ sharing_ptrt return array_abstract_objectt::write_index( environment, ns, stack, index_expr, value, merging_write); } - else + + const auto &result= + std::dynamic_pointer_cast(mutable_clone()); + + if(!stack.empty()) { - if(stack.empty()) + mp_integer index_value; + if(eval_index(index_expr, environment, ns, index_value)) { - auto result= - internal_sharing_ptrt( - new constant_array_abstract_objectt(*this)); + // We were able to evaluate the index to a value, which we + // assume is in bounds... + abstract_object_pointert starting_value; + shared_array_mapt::const_find_type old_value = map.find(index_value); - mp_integer index_value; - if(!merging_write && eval_index(index_expr, environment, ns, index_value)) + if(!old_value.second) { - if(is_top()) - { - result->clear_top(); - } - - result->map[index_value]=value; - return result; + starting_value=get_top_entry(environment, ns); } 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); + starting_value=old_value.first; } + + result->map[index_value] = + environment.write(starting_value, value, stack, ns, merging_write); + + result->clear_top(); + DATA_INVARIANT(result->verify(), "Structural invariants maintained"); + return result; } else { - auto result= - internal_sharing_ptrt( - new constant_array_abstract_objectt(*this)); + // We were not able to evaluate the index to a value + shared_array_mapt::viewt view; + map.get_view(view); - mp_integer index_value; - if(eval_index(index_expr, environment, ns, index_value)) + for(const auto &starting_value : view) { - // Here we assume the write is in bounds - abstract_object_pointert array_entry; - shared_array_mapt::const_find_type old_value = map.find(index_value); + // Merging write since we don't know which index we are writing to + result->map[starting_value.first]= + environment.write( + starting_value.second, value, stack, ns, true); + result->clear_top(); + } - if(old_value.second) - { - array_entry=old_value.first; - } - else + DATA_INVARIANT(result->verify(), "Structural invariants maintained"); + return result; + } + } + else + { + mp_integer index_value; + + if(eval_index(index_expr, environment, ns, index_value)) + { + // We were able to evalute the index expression to a constant + if(merging_write) + { + if(is_top()) { - array_entry=get_top_entry(environment, ns); + DATA_INVARIANT(result->verify(), "Structural invariants maintained"); + return result; } - if(is_top()) + INVARIANT(!result->map.empty(), "If not top, map cannot be empty"); + + shared_array_mapt::const_find_type old_value= + result->map.find(index_value); + + if(!old_value.second) // Array element is top { - result->clear_top(); + DATA_INVARIANT(result->verify(), "Structural invariants maintained"); + return result; } - result->map[index_value]=environment.write( - array_entry, value, stack, ns, merging_write); + bool dummy; + + result->map[index_value] = + abstract_objectt::merge(old_value.first, value, dummy); + + DATA_INVARIANT(result->verify(), "Structural invariants maintained"); return result; } else { - shared_array_mapt::viewt view; - map.get_view(view); - - for(const auto &array_entry : view) - { - // Merging write since we don't know which index we are writing to - result->map[array_entry.first]= - environment.write( - array_entry.second, value, stack, ns, true); - if(is_top()) - { - result->clear_top(); - } - } - + result->map[index_value] = value; + result->clear_top(); + DATA_INVARIANT(result->verify(), "Structural invariants maintained"); return result; } } + + // 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); } } diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index 57723c9efbf..ad01c74e6f1 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -35,41 +35,30 @@ class constant_array_abstract_objectt:public array_abstract_objectt void output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; - virtual abstract_object_pointert read( - const abstract_environmentt &env, - const exprt &specifier, - const namespacet &ns) const override; - - virtual abstract_object_pointert write( - abstract_environmentt &environment, - const namespacet &ns, - const std::stack stack, - const exprt &specifier, - const abstract_object_pointert value, - bool merging_write) const override; - virtual abstract_object_pointert visit_sub_elements( const abstract_object_visitort &visitor) const override; protected: CLONE - abstract_object_pointert read_index( + virtual abstract_object_pointert read_index( const abstract_environmentt &env, const index_exprt &index, - const namespacet &ns) const; + const namespacet &ns) const override; - sharing_ptrt write_index( + 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; + bool merging_write) const override; virtual abstract_object_pointert merge( abstract_object_pointert other) const override; + bool verify() const; + 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 From ab5ebd4d9ab7979536e2a7fee85c35df513f5ec8 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 25 Apr 2018 14:17:07 +0100 Subject: [PATCH 203/342] CLEANUP: Move dump_map utility functions to the correct .cpp file --- .../variable-sensitivity/abstract_object.cpp | 37 +++++++++++++++++ .../variable-sensitivity/abstract_value.cpp | 41 ------------------- 2 files changed, 37 insertions(+), 41 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index ce62823732c..223806ca92e 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -427,5 +427,42 @@ abstract_object_pointert abstract_objectt::update_location_context( return shared_from_this(); } +void abstract_objectt::dump_map( + std::ostream out, const abstract_objectt::shared_mapt &m) +{ + shared_mapt::viewt view; + m.get_view(view); + + out << "{"; + bool first=true; + for(auto &item : view) + { + out << (first ? "" : ", ") << item.first; + first = false; + } + out << "}"; +} +/** + * \brief Dump all elements in m1 that are different or missing in m2 + * + * \param m1 the 'target' sharing_map + * \param m2 the reference sharing map + */ +void abstract_objectt::dump_map_diff( + std::ostream out, + const abstract_objectt::shared_mapt &m1, + const abstract_objectt::shared_mapt &m2) +{ + shared_mapt::delta_viewt delta_view; + m1.get_delta_view(m2, delta_view, false); + out << "DELTA{"; + bool first = true; + for(auto &item : delta_view) + { + out << (first ? "" : ", ") << item.k << "=" << item.in_both; + first = false; + } + out << "}"; +} diff --git a/src/analyses/variable-sensitivity/abstract_value.cpp b/src/analyses/variable-sensitivity/abstract_value.cpp index 1990d224b5a..6a2f75a8c55 100644 --- a/src/analyses/variable-sensitivity/abstract_value.cpp +++ b/src/analyses/variable-sensitivity/abstract_value.cpp @@ -71,44 +71,3 @@ abstract_valuet::abstract_valuet( const namespacet &ns): abstract_objectt(expr, environment, ns) {} - - -void abstract_objectt::dump_map( - std::ostream out, const abstract_objectt::shared_mapt &m) -{ - shared_mapt::viewt view; - m.get_view(view); - - out << "{"; - bool first=true; - for(auto &item : view) - { - out << (first ? "" : ", ") << item.first; - first = false; - } - out << "}"; -} - -/** - * \brief Dump all elements in m1 that are different or missing in m2 - * - * \param m1 the 'target' sharing_map - * \param m2 the reference sharing map - */ -void abstract_objectt::dump_map_diff( - std::ostream out, - const abstract_objectt::shared_mapt &m1, - const abstract_objectt::shared_mapt &m2) -{ - shared_mapt::delta_viewt delta_view; - m1.get_delta_view(m2, delta_view, false); - - out << "DELTA{"; - bool first = true; - for(auto &item : delta_view) - { - out << (first ? "" : ", ") << item.k << "=" << item.in_both; - first = false; - } - out << "}"; -} From 971b02002277ee85970c3c1594173bf9c2e3355c Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 18 Apr 2018 12:32:53 +0100 Subject: [PATCH 204/342] REFACTOR: Rename dependency_context_abstract_object to write_location_context --- src/analyses/Makefile | 2 +- .../variable_sensitivity_object_factory.cpp | 20 ++++---- .../variable_sensitivity_object_factory.h | 2 +- ..._object.cpp => write_location_context.cpp} | 48 +++++++++---------- ...ract_object.h => write_location_context.h} | 34 ++++++------- 5 files changed, 53 insertions(+), 53 deletions(-) rename src/analyses/variable-sensitivity/{dependency_context_abstract_object.cpp => write_location_context.cpp} (87%) rename src/analyses/variable-sensitivity/{dependency_context_abstract_object.h => write_location_context.h} (85%) diff --git a/src/analyses/Makefile b/src/analyses/Makefile index b49ed92c594..6ebd2a66330 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -39,7 +39,7 @@ SRC = ai.cpp \ variable-sensitivity/array_abstract_object.cpp \ variable-sensitivity/constant_abstract_value.cpp \ variable-sensitivity/constant_pointer_abstract_object.cpp \ - variable-sensitivity/dependency_context_abstract_object.cpp \ + variable-sensitivity/write_location_context.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/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 6895aff9f32..0a1ce1fd315 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -101,44 +101,44 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: { case CONSTANT: return initialize_abstract_object< - context_abstract_objectt>( + typed_write_location_contextt>( followed_type, top, bottom, e, environment, ns); case ARRAY_SENSITIVE: return initialize_abstract_object< - context_abstract_objectt>( + typed_write_location_contextt>( followed_type, top, bottom, e, environment, ns); case ARRAY_INSENSITIVE: return initialize_abstract_object< - context_abstract_objectt>( + typed_write_location_contextt>( followed_type, top, bottom, e, environment, ns); case POINTER_SENSITIVE: return initialize_abstract_object< - context_abstract_objectt>( + typed_write_location_contextt>( followed_type, top, bottom, e, environment, ns); case POINTER_INSENSITIVE: return initialize_abstract_object< - context_abstract_objectt>( + typed_write_location_contextt>( followed_type, top, bottom, e, environment, ns); case STRUCT_SENSITIVE: return initialize_abstract_object< - context_abstract_objectt>( + typed_write_location_contextt>( followed_type, top, bottom, e, environment, ns); case STRUCT_INSENSITIVE: return initialize_abstract_object< - context_abstract_objectt>( + typed_write_location_contextt>( followed_type, top, bottom, e, environment, ns); case UNION_INSENSITIVE: return initialize_abstract_object< - context_abstract_objectt>( + typed_write_location_contextt>( followed_type, top, bottom, e, environment, ns); case TWO_VALUE: return initialize_abstract_object< - context_abstract_objectt>( + typed_write_location_contextt>( followed_type, top, bottom, e, environment, ns); default: UNREACHABLE; return initialize_abstract_object< - context_abstract_objectt>( + typed_write_location_contextt>( 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 978c2c26f65..e34118e19d9 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp b/src/analyses/variable-sensitivity/write_location_context.cpp similarity index 87% rename from src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp rename to src/analyses/variable-sensitivity/write_location_context.cpp index a34bd0044fb..3469d5c41c0 100644 --- a/src/analyses/variable-sensitivity/dependency_context_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/write_location_context.cpp @@ -1,6 +1,6 @@ /*******************************************************************\ - Module: analyses variable-sensitivity + Module: analyses variable-sensitivity write_location_context Author: Diffblue Ltd. @@ -9,21 +9,21 @@ #include #include #include -#include "dependency_context_abstract_object.h" +#include "write_location_context.h" -void dependency_context_abstract_objectt::set_child( +void write_location_contextt::set_child( const abstract_object_pointert &child) { child_abstract_object = child; } -void dependency_context_abstract_objectt::make_top_internal() +void write_location_contextt::make_top_internal() { if(!child_abstract_object->is_top()) set_child(child_abstract_object->make_top()); } -void dependency_context_abstract_objectt::clear_top_internal() +void write_location_contextt::clear_top_internal() { if(child_abstract_object->is_top()) set_child(child_abstract_object->clear_top()); @@ -41,12 +41,12 @@ void dependency_context_abstract_objectt::clear_top_internal() * updated */ abstract_object_pointert - dependency_context_abstract_objectt::update_location_context( + write_location_contextt::update_location_context( const abstract_objectt::locationst &locations, const bool update_sub_elements) const { const auto &result= - std::dynamic_pointer_cast( + std::dynamic_pointer_cast( mutable_clone()); if(update_sub_elements) @@ -63,7 +63,7 @@ abstract_object_pointert } abstract_objectt::locationst - dependency_context_abstract_objectt::get_last_written_locations() const + write_location_contextt::get_last_written_locations() const { return last_written_locations; } @@ -82,7 +82,7 @@ abstract_objectt::locationst * For the dependency context, the operation is simply delegated to the * child object */ -abstract_object_pointert dependency_context_abstract_objectt::read( +abstract_object_pointert write_location_contextt::read( const abstract_environmentt &env, const exprt &specifier, const namespacet &ns) const @@ -106,7 +106,7 @@ abstract_object_pointert dependency_context_abstract_objectt::read( * \return the abstract_objectt representing the result of writing * to a specific component. */ -abstract_object_pointert dependency_context_abstract_objectt::write( +abstract_object_pointert write_location_contextt::write( abstract_environmentt &environment, const namespacet &ns, const std::stack stack, @@ -125,13 +125,13 @@ abstract_object_pointert dependency_context_abstract_objectt::write( // Need to ensure the result of the write is still wrapped in a dependency // context const auto &result= - std::dynamic_pointer_cast( + std::dynamic_pointer_cast( mutable_clone()); // Update the child and record the updated write locations result->set_child(updated_child); auto value_context= - std::dynamic_pointer_cast(value); + std::dynamic_pointer_cast(value); if(value_context) { @@ -151,11 +151,11 @@ abstract_object_pointert dependency_context_abstract_objectt::write( * \return the result of the merge, or 'this' if the merge would not change * the current abstract object */ -abstract_object_pointert dependency_context_abstract_objectt::merge( +abstract_object_pointert write_location_contextt::merge( abstract_object_pointert other) const { auto cast_other= - std::dynamic_pointer_cast(other); + std::dynamic_pointer_cast(other); if(cast_other) { @@ -175,7 +175,7 @@ abstract_object_pointert dependency_context_abstract_objectt::merge( if(child_modified || merge_locations) { const auto &result= - std::dynamic_pointer_cast( + std::dynamic_pointer_cast( mutable_clone()); if(child_modified) { @@ -209,11 +209,11 @@ abstract_object_pointert dependency_context_abstract_objectt::merge( * \return the result of the merge */ abstract_object_pointert - dependency_context_abstract_objectt::abstract_object_merge_internal( + write_location_contextt::abstract_object_merge_internal( const abstract_object_pointert other) const { auto other_context= - std::dynamic_pointer_cast(other); + std::dynamic_pointer_cast(other); if(other_context) { @@ -235,7 +235,7 @@ abstract_object_pointert * * \param locations the locations to set */ -void dependency_context_abstract_objectt::set_last_written_locations( +void write_location_contextt::set_last_written_locations( const abstract_objectt::locationst &locations) { last_written_locations=locations; @@ -253,7 +253,7 @@ void dependency_context_abstract_objectt::set_last_written_locations( * \return the resolved expression */ abstract_object_pointert - dependency_context_abstract_objectt::expression_transform( + write_location_contextt::expression_transform( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns) const @@ -269,7 +269,7 @@ abstract_object_pointert * (that contains the object ... ) * \param ns the current namespace */ -void dependency_context_abstract_objectt::output( +void write_location_contextt::output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const { child_abstract_object->output(out, ai, ns); @@ -288,7 +288,7 @@ void dependency_context_abstract_objectt::output( * \return the union of this objects location set, and 'locations' */ abstract_objectt::locationst - dependency_context_abstract_objectt::get_location_union( + write_location_contextt::get_location_union( const locationst &locations) const { locationst existing_locations=get_last_written_locations(); @@ -307,7 +307,7 @@ abstract_objectt::locationst * \return true if 'this' is considered to have been modified in comparison * to 'before', false otherwise. */ -bool dependency_context_abstract_objectt::has_been_modified( +bool write_location_contextt::has_been_modified( const abstract_object_pointert before) const { if(this==before.get()) @@ -317,7 +317,7 @@ bool dependency_context_abstract_objectt::has_been_modified( } auto before_context= - std::dynamic_pointer_cast + std::dynamic_pointer_cast (before); if(!before_context) @@ -388,7 +388,7 @@ bool dependency_context_abstract_objectt::has_been_modified( * \param out the stream on which to output the locations * \param locations the set of locations to output */ -void dependency_context_abstract_objectt::output_last_written_locations( +void write_location_contextt::output_last_written_locations( std::ostream &out, const abstract_objectt::locationst &locations) { diff --git a/src/analyses/variable-sensitivity/dependency_context_abstract_object.h b/src/analyses/variable-sensitivity/write_location_context.h similarity index 85% rename from src/analyses/variable-sensitivity/dependency_context_abstract_object.h rename to src/analyses/variable-sensitivity/write_location_context.h index ccb7ebc202b..a695de55e77 100644 --- a/src/analyses/variable-sensitivity/dependency_context_abstract_object.h +++ b/src/analyses/variable-sensitivity/write_location_context.h @@ -1,12 +1,12 @@ /*******************************************************************\ - Module: analyses variable-sensitivity + Module: analyses variable-sensitivity write_location_context Author: Diffblue Ltd. \*******************************************************************/ -#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_DEPENDENCY_CONTEXT_ABSTRACT_OBJECT_H -#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_DEPENDENCY_CONTEXT_ABSTRACT_OBJECT_H +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_LOCATION_CONTEXT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_LOCATION_CONTEXT_H #include #include @@ -24,12 +24,12 @@ * of this, 'context_abstract_objectt' which provides the same * constructors as the standard 'abstract_objectt' class. */ -class dependency_context_abstract_objectt: public abstract_objectt +class write_location_contextt: public abstract_objectt { public: // These constructors mirror those in the base abstract_objectt, but with // the addition of an extra argument which is the abstract_objectt to wrap. - explicit dependency_context_abstract_objectt( + explicit write_location_contextt( const abstract_object_pointert child, const typet &type): abstract_objectt(type) @@ -37,7 +37,7 @@ class dependency_context_abstract_objectt: public abstract_objectt child_abstract_object = child; } - dependency_context_abstract_objectt( + write_location_contextt( const abstract_object_pointert child, const typet &type, bool top, @@ -47,7 +47,7 @@ class dependency_context_abstract_objectt: public abstract_objectt child_abstract_object = child; } - explicit dependency_context_abstract_objectt( + explicit write_location_contextt( const abstract_object_pointert child, const exprt &expr, const abstract_environmentt &environment, @@ -57,7 +57,7 @@ class dependency_context_abstract_objectt: public abstract_objectt child_abstract_object = child; } - virtual ~dependency_context_abstract_objectt() {} + virtual ~write_location_contextt() {} // Standard abstract_objectt interface @@ -170,32 +170,32 @@ class dependency_context_abstract_objectt: public abstract_objectt * context information */ template -class context_abstract_objectt: public dependency_context_abstract_objectt +class typed_write_location_contextt: public write_location_contextt { public: - explicit context_abstract_objectt(const typet &type): - dependency_context_abstract_objectt( + explicit typed_write_location_contextt(const typet &type): + write_location_contextt( abstract_object_pointert(new AOT(type)), type) {} - context_abstract_objectt( + typed_write_location_contextt( const typet &type, bool top, bool bottom): - dependency_context_abstract_objectt( + write_location_contextt( abstract_object_pointert(new AOT(type, top, bottom)), type, top, bottom) {} - explicit context_abstract_objectt( + explicit typed_write_location_contextt( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns): - dependency_context_abstract_objectt( + write_location_contextt( abstract_object_pointert(new AOT(expr, environment, ns)), expr, environment, ns) {} }; -// NOLINTNEXTLINE(whitespace/line_length) -#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_DEPENDENCY_CONTEXT_ABSTRACT_OBJECT_H + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_LOCATION_CONTEXT_H From 9bdb2010fe5acefa3eb2cbfd92552d0da1934553 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Thu, 19 Apr 2018 17:05:21 +0100 Subject: [PATCH 205/342] REFACTOR: Refactor variable sensitivity write_location_context --- src/analyses/Makefile | 1 + .../context_abstract_object.cpp | 148 ++++++++++++++++++ .../context_abstract_object.h | 115 ++++++++++++++ .../write_location_context.cpp | 62 +------- .../write_location_context.h | 76 ++------- 5 files changed, 281 insertions(+), 121 deletions(-) create mode 100644 src/analyses/variable-sensitivity/context_abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/context_abstract_object.h diff --git a/src/analyses/Makefile b/src/analyses/Makefile index 6ebd2a66330..7b9d30abecf 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -39,6 +39,7 @@ SRC = ai.cpp \ variable-sensitivity/array_abstract_object.cpp \ variable-sensitivity/constant_abstract_value.cpp \ variable-sensitivity/constant_pointer_abstract_object.cpp \ + variable-sensitivity/context_abstract_object.cpp \ variable-sensitivity/write_location_context.cpp \ variable-sensitivity/pointer_abstract_object.cpp \ variable-sensitivity/struct_abstract_object.cpp \ diff --git a/src/analyses/variable-sensitivity/context_abstract_object.cpp b/src/analyses/variable-sensitivity/context_abstract_object.cpp new file mode 100644 index 00000000000..cb7c3140b88 --- /dev/null +++ b/src/analyses/variable-sensitivity/context_abstract_object.cpp @@ -0,0 +1,148 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity context_abstract_object + + Author: Diffblue Ltd + +\*******************************************************************/ + +#include "context_abstract_object.h" + + +void context_abstract_objectt::set_child( + const abstract_object_pointert &child) +{ + child_abstract_object = child; +} + +void context_abstract_objectt::make_top_internal() +{ + if(!child_abstract_object->is_top()) + set_child(child_abstract_object->make_top()); +} + +void context_abstract_objectt::clear_top_internal() +{ + if(child_abstract_object->is_top()) + set_child(child_abstract_object->clear_top()); +} + +/** + * A helper function to evaluate an abstract object contained + * within a container object. More precise abstractions may override this + * to return more precise results. + * + * \param env the abstract environment + * \param specifier a modifier expression, such as an array index or field + * specifier used to indicate access to a specific component + * \param ns the current namespace + * + * \return the abstract_objectt representing the value of the read component. + * For the dependency context, the operation is simply delegated to the + * child object + */ +abstract_object_pointert context_abstract_objectt::read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const +{ + return child_abstract_object->read(env, specifier, ns); +} + +/** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ +abstract_object_pointert context_abstract_objectt::write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const +{ + abstract_object_pointert updated_child= + child_abstract_object->write( + environment, ns, stack, specifier, value, merging_write); + + // Only perform an update if the write to the child has in fact changed it... + if(updated_child == child_abstract_object) + return shared_from_this(); + + // Need to ensure the result of the write is still wrapped in a context + const auto &result= + std::dynamic_pointer_cast( + mutable_clone()); + + // Update the child and record the updated write locations + result->set_child(updated_child); + + return result; +} + +/** + * Try to resolve an expression with the maximum level of precision + * available. + * + * \param expr the expression to evaluate and find the result of. This will + * be the symbol referred to be op0() + * \param environment the abstract environment in which to resolve 'expr' + * \param ns the current namespace + * + * \return the resolved expression + */ +abstract_object_pointert context_abstract_objectt::expression_transform( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const +{ + return child_abstract_object->expression_transform(expr, environment, ns); +} + +/** + * Output a representation of the value of this abstract object + * + * \param out the stream to write to + * \param ai the abstract interpreter that contains the abstract domain + * (that contains the object ... ) + * \param ns the current namespace + */ +void context_abstract_objectt::output( + std::ostream &out, const ai_baset &ai, const namespacet &ns) const +{ + child_abstract_object->output(out, ai, ns); +} + +/** + * Determine whether 'this' abstract_object has been modified in comparison + * to a previous 'before' state. + * \param before The abstract_object_pointert to use as a reference to + * compare against + * \return true if 'this' is considered to have been modified in comparison + * to 'before', false otherwise. + */ +bool context_abstract_objectt::has_been_modified( + const abstract_object_pointert before) const +{ + // Default implementation, with no other information to go on + // falls back to relying on copy-on-write and pointer inequality + // to indicate if an abstract_objectt has been modified + auto before_context= + std::dynamic_pointer_cast + (before); + + return this->child_abstract_object.get() != + before_context->child_abstract_object.get(); +}; diff --git a/src/analyses/variable-sensitivity/context_abstract_object.h b/src/analyses/variable-sensitivity/context_abstract_object.h new file mode 100644 index 00000000000..734dda7d569 --- /dev/null +++ b/src/analyses/variable-sensitivity/context_abstract_object.h @@ -0,0 +1,115 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity context_abstract_object + + Author: Diffblue Ltd + +\*******************************************************************/ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONTEXT_ABSTRACT_OBJECT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONTEXT_ABSTRACT_OBJECT_H + +#include + +/** + * General implementation of a an abstract_objectt which can track + * side information in the form of a 'context' associated with a wrapped + * abstract_objectt of some other type. This class is not intended to be + * instantiated directly - instead it is intended to be inherited from for + * other classes to define what the context actually means. + */ +class context_abstract_objectt: public abstract_objectt +{ +public: + // These constructors mirror those in the base abstract_objectt, but with + // the addition of an extra argument which is the abstract_objectt to wrap. + explicit context_abstract_objectt( + const abstract_object_pointert child, + const typet &type): + abstract_objectt(type) + { + child_abstract_object = child; + } + + context_abstract_objectt( + const abstract_object_pointert child, + const typet &type, + bool top, + bool bottom): + abstract_objectt(type, top, bottom) + { + child_abstract_object = child; + } + + explicit context_abstract_objectt( + const abstract_object_pointert child, + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns): + abstract_objectt(expr, environment, ns) + { + child_abstract_object = child; + } + + virtual ~context_abstract_objectt() {} + + virtual const typet &type() const + { + return child_abstract_object->type(); + } + + virtual bool is_top() const override + { + return child_abstract_object->is_top(); + } + + virtual bool is_bottom() const override + { + return child_abstract_object->is_bottom(); + } + + virtual exprt to_constant() const override + { + return child_abstract_object->to_constant(); + } + + abstract_object_pointert expression_transform( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const; + + virtual void output( + std::ostream &out, const class ai_baset &ai, const namespacet &ns) const + override; + +protected: + CLONE + + // The abstract_objectt that will be wrapped in a context + abstract_object_pointert child_abstract_object; + + void set_child( + const abstract_object_pointert &child); + + // These are internal hooks that allow sub-classes to perform additional + // actions when an abstract_object is set/unset to TOP + virtual void make_top_internal() override; + virtual void clear_top_internal() override; + + virtual abstract_object_pointert read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const override; + + virtual abstract_object_pointert write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const override; + + virtual bool has_been_modified(const abstract_object_pointert before) const + override; +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONTEXT_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/write_location_context.cpp b/src/analyses/variable-sensitivity/write_location_context.cpp index 3469d5c41c0..4954eac7d22 100644 --- a/src/analyses/variable-sensitivity/write_location_context.cpp +++ b/src/analyses/variable-sensitivity/write_location_context.cpp @@ -11,24 +11,6 @@ #include #include "write_location_context.h" -void write_location_contextt::set_child( - const abstract_object_pointert &child) -{ - child_abstract_object = child; -} - -void write_location_contextt::make_top_internal() -{ - if(!child_abstract_object->is_top()) - set_child(child_abstract_object->make_top()); -} - -void write_location_contextt::clear_top_internal() -{ - if(child_abstract_object->is_top()) - set_child(child_abstract_object->clear_top()); -} - /** * Update the location context for an abstract object, potentially * propogating the update to any children of this abstract object. @@ -68,28 +50,6 @@ abstract_objectt::locationst return last_written_locations; } -/** - * A helper function to evaluate an abstract object contained - * within a container object. More precise abstractions may override this - * to return more precise results. - * - * \param env the abstract environment - * \param specifier a modifier expression, such as an array index or field - * specifier used to indicate access to a specific component - * \param ns the current namespace - * - * \return the abstract_objectt representing the value of the read component. - * For the dependency context, the operation is simply delegated to the - * child object - */ -abstract_object_pointert write_location_contextt::read( - const abstract_environmentt &env, - const exprt &specifier, - const namespacet &ns) const -{ - return child_abstract_object->read(env, specifier, ns); -} - /** * A helper function to evaluate writing to a component of an * abstract object. More precise abstractions may override this to @@ -241,26 +201,6 @@ void write_location_contextt::set_last_written_locations( last_written_locations=locations; } -/** - * Try to resolve an expression with the maximum level of precision - * available. - * - * \param expr the expression to evaluate and find the result of. This will - * be the symbol referred to be op0() - * \param environment the abstract environment in which to resolve 'expr' - * \param ns the current namespace - * - * \return the resolved expression - */ -abstract_object_pointert - write_location_contextt::expression_transform( - const exprt &expr, - const abstract_environmentt &environment, - const namespacet &ns) const -{ - return child_abstract_object->expression_transform(expr, environment, ns); -} - /** * Output a representation of the value of this abstract object * @@ -272,7 +212,7 @@ abstract_object_pointert void write_location_contextt::output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const { - child_abstract_object->output(out, ai, ns); + context_abstract_objectt::output(out, ai, ns); // Output last written locations immediately following the child output out << " @ "; diff --git a/src/analyses/variable-sensitivity/write_location_context.h b/src/analyses/variable-sensitivity/write_location_context.h index a695de55e77..23c874530d8 100644 --- a/src/analyses/variable-sensitivity/write_location_context.h +++ b/src/analyses/variable-sensitivity/write_location_context.h @@ -5,13 +5,20 @@ Author: Diffblue Ltd. \*******************************************************************/ + +/** + * \file + * Maintain a context in the variable sensitvity domain that records + * write locations for a given abstract_objectt. This enables more + * accurate merging at three_way_merge. + */ + #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_LOCATION_CONTEXT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_LOCATION_CONTEXT_H #include -#include +#include #include -#include "array_abstract_object.h" /** * General implementation of an abstract_objectt which tracks the @@ -24,38 +31,27 @@ * of this, 'context_abstract_objectt' which provides the same * constructors as the standard 'abstract_objectt' class. */ -class write_location_contextt: public abstract_objectt +class write_location_contextt: public context_abstract_objectt { public: - // These constructors mirror those in the base abstract_objectt, but with - // the addition of an extra argument which is the abstract_objectt to wrap. explicit write_location_contextt( const abstract_object_pointert child, const typet &type): - abstract_objectt(type) - { - child_abstract_object = child; - } + context_abstract_objectt(child, type) { } write_location_contextt( const abstract_object_pointert child, const typet &type, bool top, bool bottom): - abstract_objectt(type, top, bottom) - { - child_abstract_object = child; - } + context_abstract_objectt(child, type, top, bottom) { } explicit write_location_contextt( const abstract_object_pointert child, const exprt &expr, const abstract_environmentt &environment, const namespacet &ns): - abstract_objectt(expr, environment, ns) - { - child_abstract_object = child; - } + context_abstract_objectt(child, expr, environment, ns) { } virtual ~write_location_contextt() {} @@ -88,34 +84,9 @@ class write_location_contextt: public abstract_objectt locationst get_location_union(const locationst &locations) const; - virtual const typet &type() const - { - return child_abstract_object->type(); - } - - virtual bool is_top() const override - { - return child_abstract_object->is_top(); - } - - virtual bool is_bottom() const override - { - return child_abstract_object->is_bottom(); - } - - abstract_object_pointert expression_transform( - const exprt &expr, - const abstract_environmentt &environment, - const namespacet &ns) const; - - virtual exprt to_constant() const override - { - return child_abstract_object->to_constant(); - } - virtual void output( std::ostream &out, const class ai_baset &ai, const namespacet &ns) const - override; + override; protected: @@ -124,10 +95,8 @@ class write_location_contextt: public abstract_objectt virtual abstract_object_pointert merge( abstract_object_pointert other) const override; - virtual abstract_object_pointert read( - const abstract_environmentt &env, - const exprt &specifier, - const namespacet &ns) const override; + virtual abstract_object_pointert abstract_object_merge_internal( + const abstract_object_pointert other) const override; virtual abstract_object_pointert write( abstract_environmentt &environment, @@ -146,24 +115,11 @@ class write_location_contextt: public abstract_objectt private: // To enforce copy-on-write these are private and have read-only accessors abstract_objectt::locationst last_written_locations; - abstract_object_pointert child_abstract_object; - - // These are internal hooks that allow sub-classes to perform additional - // actions when an abstract_object is set/unset to TOP - virtual void make_top_internal() override; - virtual void clear_top_internal() override; - - virtual abstract_object_pointert abstract_object_merge_internal( - const abstract_object_pointert other) const override; void set_last_written_locations( const abstract_objectt::locationst &locations); - - void set_child( - const abstract_object_pointert &child); }; - /** * Templated extension of the abstract implementation, used as a wrapper around * other abstract_objectt classes to enable the factory to instantiate the From b503ec94a230543b44ac4a1b1cfb8dbadc9e8514 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 18 Apr 2018 11:46:21 +0100 Subject: [PATCH 206/342] Record struct initialisation when field sensitivity is turned on Currently, full_struct_abstract_object does not properly track static initialisation of a struct value. This commit ensures that when a struct is initialised with a static value, the appropriate field values are also tracked. --- .../struct-initialization.c | 53 +++++++++++++++++++ .../test.desc | 31 +++++++++++ .../full_struct_abstract_object.cpp | 21 ++++++++ 3 files changed, 105 insertions(+) create mode 100644 regression/goto-analyzer/sensitivity-test-struct-initialization/struct-initialization.c create mode 100644 regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc diff --git a/regression/goto-analyzer/sensitivity-test-struct-initialization/struct-initialization.c b/regression/goto-analyzer/sensitivity-test-struct-initialization/struct-initialization.c new file mode 100644 index 00000000000..1cfa00ad9c2 --- /dev/null +++ b/regression/goto-analyzer/sensitivity-test-struct-initialization/struct-initialization.c @@ -0,0 +1,53 @@ +struct lexigraphically_ordered_struct { + int a; + int b; +}; + +struct lexigraphically_unordered_struct { + int b; + int a; +}; + +struct lexigraphically_ordered_struct los; +struct lexigraphically_ordered_struct los2 = {.a=3, .b=4}; +struct lexigraphically_ordered_struct los3 = {.b=4, .a=3}; +struct lexigraphically_ordered_struct los4 = {.a=3}; +struct lexigraphically_ordered_struct los5 = {.b=4}; +struct lexigraphically_ordered_struct los6 = {3, 4}; + +struct lexigraphically_unordered_struct lus; +struct lexigraphically_unordered_struct lus2 = {.a=3, .b=4}; +struct lexigraphically_unordered_struct lus3 = {.b=4, .a=3}; +struct lexigraphically_unordered_struct lus4 = {.a=3}; +struct lexigraphically_unordered_struct lus5 = {.b=4}; +struct lexigraphically_unordered_struct lus6 = {4, 3}; + +void main(void) +{ + __CPROVER_assert(los.a==0, "los.a==0"); + __CPROVER_assert(los.b==0, "los.b==0"); + __CPROVER_assert(los2.a==3, "los2.a==3"); + __CPROVER_assert(los2.b==4, "los2.b==4"); + __CPROVER_assert(los3.a==3, "los3.a==3"); + __CPROVER_assert(los3.b==4, "los3.b==4"); + __CPROVER_assert(los4.a==3, "los4.a==3"); + __CPROVER_assert(los4.b==0, "los4.b==0"); + __CPROVER_assert(los5.a==0, "los5.a==0"); + __CPROVER_assert(los5.b==4, "los5.b==4"); + __CPROVER_assert(los6.a==3, "los6.a==3"); + __CPROVER_assert(los6.b==4, "los6.b==4"); + + __CPROVER_assert(lus.a==0, "lus.a==0"); + __CPROVER_assert(lus.b==0, "lus.b==0"); + __CPROVER_assert(lus2.a==3, "lus2.a==3"); + __CPROVER_assert(lus2.b==4, "lus2.b==4"); + __CPROVER_assert(lus3.a==3, "lus3.a==3"); + __CPROVER_assert(lus3.b==4, "lus3.b==4"); + __CPROVER_assert(lus4.a==3, "lus4.a==3"); + __CPROVER_assert(lus4.b==0, "lus4.b==0"); + __CPROVER_assert(lus5.a==0, "lus5.a==0"); + __CPROVER_assert(lus5.b==4, "lus5.b==4"); + __CPROVER_assert(lus6.a==3, "lus6.a==3"); + __CPROVER_assert(lus6.b==4, "lus6.b==4"); +} + diff --git a/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc b/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc new file mode 100644 index 00000000000..70491115d3e --- /dev/null +++ b/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc @@ -0,0 +1,31 @@ +CORE +struct-initialization.c +--variable --structs --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] .* los.a==0: Success$ +^\[main.assertion.2\] .* los.b==0: Success$ +^\[main.assertion.3\] .* los2.a==3: Success$ +^\[main.assertion.4\] .* los2.b==4: Success$ +^\[main.assertion.5\] .* los3.a==3: Success$ +^\[main.assertion.6\] .* los3.b==4: Success$ +^\[main.assertion.7\] .* los4.a==3: Success$ +^\[main.assertion.8\] .* los4.b==0: Success$ +^\[main.assertion.9\] .* los5.a==0: Success$ +^\[main.assertion.10\] .* los5.b==4: Success$ +^\[main.assertion.11\] .* los6.a==3: Success$ +^\[main.assertion.12\] .* los6.b==4: Success$ +^\[main.assertion.13\] .* lus.a==0: Success$ +^\[main.assertion.14\] .* lus.b==0: Success$ +^\[main.assertion.15\] .* lus2.a==3: Success$ +^\[main.assertion.16\] .* lus2.b==4: Success$ +^\[main.assertion.17\] .* lus3.a==3: Success$ +^\[main.assertion.18\] .* lus3.b==4: Success$ +^\[main.assertion.19\] .* lus4.a==3: Success$ +^\[main.assertion.20\] .* lus4.b==0: Success$ +^\[main.assertion.21\] .* lus5.a==0: Success$ +^\[main.assertion.22\] .* lus5.b==4: Success$ +^\[main.assertion.23\] .* lus6.a==3: Success$ +^\[main.assertion.24\] .* lus6.b==4: Success$ +-- +^warning: ignoring diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 21e971ae228..b0dc3c3c82a 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -96,6 +96,27 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( const namespacet &ns): struct_abstract_objectt(e, environment, ns) { + PRECONDITION(ns.follow(e.type()).id()==ID_struct); + + const struct_typet struct_type_def = to_struct_type(ns.follow(e.type())); + + bool did_initialize_values = false; + auto struct_type_it = struct_type_def.components().begin(); + for(auto param_it = e.operands().begin(); + param_it != e.operands().end(); + ++param_it) + { + map[struct_type_it->get_name()]=environment.abstract_object_factory + (param_it->type(), *param_it, ns); + did_initialize_values = true; + ++struct_type_it; + } + + if(did_initialize_values) + { + clear_top(); + } + DATA_INVARIANT(verify(), "Structural invariants maintained"); } From b62e46d8d39950e42f70e6043d7691f78a244741 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Tue, 17 Apr 2018 15:33:29 +0100 Subject: [PATCH 207/342] Adjust float expression in variable sensitivity domain --- src/analyses/variable-sensitivity/abstract_object.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 223806ca92e..3632a401dec 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include "abstract_object.h" @@ -182,12 +183,14 @@ abstract_object_pointert abstract_objectt::expression_transform( const abstract_environmentt &environment, const namespacet &ns) const { - exprt constant_replaced_expr=expr; + exprt adjusted_expr = expr; + adjust_float_expressions(adjusted_expr, ns); + exprt constant_replaced_expr = adjusted_expr; constant_replaced_expr.operands().clear(); // Two passes over the expression - one for simplification, // another to check if there are any top subexpressions left - for(const exprt &op : expr.operands()) + for(const exprt &op : adjusted_expr.operands()) { abstract_object_pointert lhs_abstract_object=environment.eval(op, ns); const exprt &lhs_value=lhs_abstract_object->to_constant(); @@ -204,7 +207,6 @@ abstract_object_pointert abstract_objectt::expression_transform( constant_replaced_expr.operands().push_back(lhs_value); } } - exprt simplified = simplify_expr(constant_replaced_expr, ns); for(const exprt &op : simplified.operands()) From 9ce32a862c95e2a4b408fd985c82e1737c7899d6 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 25 Apr 2018 15:59:51 +0100 Subject: [PATCH 208/342] Try all rounding modes when rounding mode is unknown For variable sensitivity domain. If we don't know the rounding mode (i.e. it's not a constant known value), we can still often evaluate expressions involving floating points if the results don't change based on floating point (which is going to be the case with floating point operations that have exact results or comparisons) --- .../variable-sensitivity/abstract_object.cpp | 57 +++++++++++++++++++ .../variable-sensitivity/abstract_object.h | 5 ++ 2 files changed, 62 insertions(+) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 3632a401dec..8877ef815be 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -6,6 +6,7 @@ \*******************************************************************/ +#include #include #include @@ -16,6 +17,8 @@ #include #include #include +#include +#include #include "abstract_object.h" @@ -183,6 +186,17 @@ abstract_object_pointert abstract_objectt::expression_transform( const abstract_environmentt &environment, const namespacet &ns) const { + // try finding the rounding mode. If it's not constant, try + // seeing if we can get the same result with all rounding modes + auto rounding_mode_symbol = + symbol_exprt("__CPROVER_rounding_mode", signedbv_typet(32)); + auto rounding_mode_value = environment.eval(rounding_mode_symbol, ns); + auto rounding_mode_constant = rounding_mode_value->to_constant(); + if(rounding_mode_constant.is_nil()) + { + return try_transform_expr_with_all_rounding_modes(expr, environment, ns); + } + exprt adjusted_expr = expr; adjust_float_expressions(adjusted_expr, ns); exprt constant_replaced_expr = adjusted_expr; @@ -223,6 +237,49 @@ abstract_object_pointert abstract_objectt::expression_transform( return environment.abstract_object_factory(simplified.type(), simplified, ns); } +abstract_object_pointert +abstract_objectt::try_transform_expr_with_all_rounding_modes( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const +{ + const symbol_exprt rounding_mode_symbol = + symbol_exprt("__CPROVER_rounding_mode", signedbv_typet(32)); + // NOLINTNEXTLINE (whitespace/braces) + auto rounding_modes = std::array{ + // NOLINTNEXTLINE (whitespace/braces) + {ieee_floatt::ROUND_TO_EVEN, + ieee_floatt::ROUND_TO_ZERO, + ieee_floatt::ROUND_TO_MINUS_INF, + // NOLINTNEXTLINE (whitespace/braces) + ieee_floatt::ROUND_TO_PLUS_INF}}; + std::vector possible_results; + for(auto current_rounding_mode : rounding_modes) + { + abstract_environmentt child_env(environment); + child_env.assign( + rounding_mode_symbol, + child_env.abstract_object_factory( + signedbv_typet(32), + from_integer( + mp_integer(static_cast(current_rounding_mode)), + signedbv_typet(32)), + ns), + ns); + possible_results.push_back(expression_transform(expr, child_env, ns)); + } + auto first = possible_results.front()->to_constant(); + for(auto const &possible_result : possible_results) + { + auto current = possible_result->to_constant(); + if(current.is_nil() || current != first) + { + return environment.abstract_object_factory(expr.type(), ns); + } + } + return possible_results.front(); +} + /** * A helper function to evaluate an abstract object contained * within a container object. More precise abstractions may override this diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index aa77d17a508..c3316c2ffec 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -255,6 +255,11 @@ 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; this->make_top_internal(); } void clear_top() { top=false; this->clear_top_internal(); } + + abstract_object_pointert try_transform_expr_with_all_rounding_modes( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const; }; template From 44b00c68f1aaf6caa4cd893749c5aee553d4b47c Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 25 Apr 2018 17:04:29 +0100 Subject: [PATCH 209/342] Add floating point simplifcation test --- .../main.c | 41 +++++++++++++++++++ .../test.desc | 9 ++++ 2 files changed, 50 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-floating-point-simplification/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-floating-point-simplification/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/main.c b/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/main.c new file mode 100644 index 00000000000..60fa538c805 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/main.c @@ -0,0 +1,41 @@ +#include + +int main(void) +{ + const float one = 1.0f; + // Check that rounding mode affects behavior + + // default rounding mode towards nearest + float big_0_1 = one / 10.0f; + __CPROVER_rounding_mode = 1; // round to -∞ + float small_0_1 = one / 10.0f; + assert(small_0_1 < big_0_1); + + // Check that exact operations still work with unknown rounding mode + int some_condition; + if(some_condition) + { + __CPROVER_rounding_mode = 3; + } + // rounding mode is TOP now + + // regardless of rounding mode, + // 1/10 is definitely smaller than 0.2 + assert(one / 10.0f < 0.2f); + + // This is unknown because + // we don't know the value of one_tenth_ish + // (could be slightly less or slightly more than 0.1) + // This is contrast to above, where we didn't need + // to know the exact value of one/10.0f, just + // that it is less than 0.2f + float one_tenth_ish = one / 10.0f; + assert(one_tenth_ish < 0.2f); + + // regardless of rounding mode, + // 10/5 is still 2 + float five = 5.0f; + assert(10.0f / five == 2.0f); + + return 0; +} diff --git a/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/test.desc b/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/test.desc new file mode 100644 index 00000000000..13d621c5d9e --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/test.desc @@ -0,0 +1,9 @@ +CORE +main.c +--variable --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] file main.c line \d\d function main, assertion small_0_1 < big_0_1: Success +^\[main.assertion.2\] file main.c line \d\d function main, assertion one / 10.0f < 0.2f: Success +^\[main.assertion.3\] file main.c line \d\d function main, assertion one_tenth_ish < 0.2f: Unknown +^\[main.assertion.4\] file main.c line \d\d function main, assertion 10.0f / five == 2.0f: Success From 67d799bee5bdf3f43e9e3715a229495cb4fb669e Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 18 Apr 2018 11:51:15 +0100 Subject: [PATCH 210/342] Add data-dependency-context to variable sensitivity as commandline option This commit adds an extra 'sensitivity' to the variable sensitivity domain that enables it to track data-dependencies as an additional context on 'abstract_objectt's --- .../data-dependency-context.c | 48 +++ .../test.desc | 12 + .../data_dependency_context.cpp | 315 ++++++++++++++++++ .../data_dependency_context.h | 113 +++++++ .../variable_sensitivity_object_factory.cpp | 53 ++- .../variable_sensitivity_object_factory.h | 46 ++- .../write_location_context.h | 34 -- 7 files changed, 555 insertions(+), 66 deletions(-) create mode 100644 regression/goto-analyzer/sensitivity-test-data-dependency-context/data-dependency-context.c create mode 100644 regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc create mode 100644 src/analyses/variable-sensitivity/data_dependency_context.cpp create mode 100644 src/analyses/variable-sensitivity/data_dependency_context.h diff --git a/regression/goto-analyzer/sensitivity-test-data-dependency-context/data-dependency-context.c b/regression/goto-analyzer/sensitivity-test-data-dependency-context/data-dependency-context.c new file mode 100644 index 00000000000..80b466c1c03 --- /dev/null +++ b/regression/goto-analyzer/sensitivity-test-data-dependency-context/data-dependency-context.c @@ -0,0 +1,48 @@ +struct structt { + int a; + int b; +}; + +struct structt st; +int ar[2]; +int arr[3]; + +extern int in; +int out1, out2, out3; + +void main(void) +{ + int i; + if (in == 1) + st.a++; + + if (in == 2) + st.b++; + + out1 = st.a; + out2 = st.b; + out3 = st.a + st.b; + + if (in == 1) + ar[0]++; + + if (in == 2) + ar[1]++; + + out1 = ar[0]; + out2 = ar[1]; + out3 = ar[0] + ar[1]; + + arr[0] = 1; + arr[1] = 2; + arr[2] = 3; + + if (in > 0) + { + arr[2] = arr[1]; + } + + out1 = arr[0]; + out2 = arr[1]; + out3 = arr[2]; +} diff --git a/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc b/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc new file mode 100644 index 00000000000..c438c60068d --- /dev/null +++ b/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc @@ -0,0 +1,12 @@ +CORE +data-dependency-context.c +--variable --structs --arrays --data-dependencies --show +// Enable multi-line checking +activate-multi-line-match +EXIT=0 +SIGNAL=0 +st \(\) -> \{.a=.* @ \[2, 47\]\[Data dependencies: 47, 2\]\[Data dominators: \], .b=.* @ \[5, 47\]\[Data dependencies: 47, 5\]\[Data dominators: \]\} @ \[2, 5, 47\]\[Data dependencies: 47, 5, 2\]\[Data dominators: 47\] +ar \(\) -> \{\[0\] = .* @ \[11, 42\]\[Data dependencies: 42, 11\]\[Data dominators: \]\n\[1\] = .* @ \[14, 42\]\[Data dependencies: 42, 14\]\[Data dominators: \]\n\} @ \[11, 14, 42\]\[Data dependencies: 42, 14, 11\]\[Data dominators: 42\] +arr \(\) -> \{\[0\] = .* @ \[19\]\[Data dependencies: 19\]\[Data dominators: 19\]\n\[1\] = .* @ \[20\]\[Data dependencies: 20\]\[Data dominators: 20\]\n\[2\] = .* @ \[21, 23\]\[Data dependencies: 23, 21, 20\]\[Data dominators: \]\n\} @ \[21, 23\]\[Data dependencies: 43, 23, 21, 20, 19\]\[Data dominators: 43\] +-- +^warning: ignoring diff --git a/src/analyses/variable-sensitivity/data_dependency_context.cpp b/src/analyses/variable-sensitivity/data_dependency_context.cpp new file mode 100644 index 00000000000..f7f0ad439c7 --- /dev/null +++ b/src/analyses/variable-sensitivity/data_dependency_context.cpp @@ -0,0 +1,315 @@ +/*******************************************************************\ + +Module: analyses variable-sensitivity data_dependency_context + +Author: Diffblue Ltd + +\*******************************************************************/ + +/** + * \file + * Maintain data dependencies as a context in the variable sensitivity domain + */ + +#include +#include + +#include "data_dependency_context.h" + +/** + * Determine whether 'this' abstract_object has been modified in comparison + * to a previous 'before' state. + * + * \param before the abstract_object_pointert to use as a reference to + * compare against + * + * \return true if 'this' is considered to have been modified in comparison + * to 'before', false otherwise. + */ +bool data_dependency_contextt::has_been_modified( + const abstract_object_pointert before) const +{ + if(this->write_location_contextt::has_been_modified(before)) + return true; + + auto cast_before= + std::dynamic_pointer_cast + (before); + + if(!cast_before) + { + // The other context is not something we understand, so must assume + // that the abstract_object has been modified + return true; + } + + // Check whether the data dependencies have changed as well + abstract_objectt::locationst intersection; + std::set_intersection( + data_deps.cbegin(), + data_deps.cend(), + cast_before->data_deps.cbegin(), + cast_before->data_deps.cend(), + std::inserter(intersection, intersection.end()), + location_ordert()); + bool all_matched=intersection.size()==data_deps.size() && + intersection.size()==cast_before->data_deps.size(); + + if(!all_matched) + return true; + + intersection.clear(); + std::set_intersection( + data_dominators.cbegin(), + data_dominators.cend(), + cast_before->data_dominators.cbegin(), + cast_before->data_dominators.cend(), + std::inserter(intersection, intersection.end()), + location_ordert()); + + all_matched=intersection.size()==data_dominators.size() && + intersection.size()==cast_before->data_dominators.size(); + + return !all_matched; +} + +/** + * Insert the given set of data dependencies into the data dependencies set + * for this data_dependency_context object. + * + * \param dependencies the set of dependencies to add + * \return a new data_dependency_context if new dependencies were added, + * or 'this' if no addtional dependencies were added. + */ +abstract_object_pointert data_dependency_contextt::insert_data_deps( + const dependencest &dependencies) const +{ + // If this is the first write to the context then it is also used as + // the initial set of data dependency dominators as well. + const bool first_write = data_deps.empty(); + dependencest new_dependencies; + + // Workout what new data dependencies need to be inserted + if(first_write) + { + new_dependencies = dependencies; + } + else + { + std::set_difference( + dependencies.begin(), dependencies.end(), + data_deps.begin(), data_deps.end(), + std::inserter(new_dependencies, new_dependencies.begin())); + } + + // If there are no new dependencies to add, just return + if(new_dependencies.empty()) + return shared_from_this(); + + const auto &result= + std::dynamic_pointer_cast(mutable_clone()); + + for(auto l : new_dependencies) + { + result->data_deps.insert(l); + } + + if(first_write) + { + // If this was the first insertion of any dependencies, then these + // data dependencies are also data dominators as well + for(auto l : new_dependencies) + { + result->data_dominators.insert(l); + } + } + return result; +} + +/** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ +abstract_object_pointert data_dependency_contextt::write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const +{ + const auto updated_parent = + std::dynamic_pointer_cast( + this->write_location_contextt::write( + environment, ns, stack, specifier, value, merging_write)); + + const auto cast_value= + std::dynamic_pointer_cast(value); + + return updated_parent->insert_data_deps(cast_value->data_deps); +} + +/** + * Update the location context for an abstract object, potentially + * propogating the update to any children of this abstract object. + * + * \param locations the set of locations to be updated + * \param update_sub_elements if true, propogate the update operation to any + * children of this abstract object + * + * \return a clone of this abstract object with it's location context + * updated + */ +abstract_object_pointert +data_dependency_contextt::update_location_context( + const abstract_objectt::locationst &locations, + const bool update_sub_elements) const +{ + const auto updated_parent = + std::dynamic_pointer_cast( + this->write_location_contextt::update_location_context( + locations, update_sub_elements)); + + return updated_parent->insert_data_deps(locations); +} + +/** + * Create a new abstract object that is the result of merging this abstract + * object with a given abstract_object + * + * \param other the abstract object to merge with + * + * \return the result of the merge, or 'this' if the merge would not change + * the current abstract object + */ +abstract_object_pointert data_dependency_contextt::merge( + abstract_object_pointert other) const +{ + auto cast_other= + std::dynamic_pointer_cast(other); + + if(cast_other) + { + const auto merged_parent = + std::dynamic_pointer_cast( + this->write_location_contextt::merge(other)); + + const auto updated_parent = + std::dynamic_pointer_cast( + merged_parent->insert_data_deps(cast_other->data_deps)); + + const auto &result= + std::dynamic_pointer_cast( + updated_parent->mutable_clone()); + + // On a merge, data_dominators are the intersection of this object and the + // other object. In other words, the dominators at this merge point are + // those dominators that exist in all possible execution paths to this + // merge point. + result->data_dominators.clear(); + std::set_intersection( + data_dominators.begin(), data_dominators.end(), + cast_other->data_dominators.begin(), cast_other->data_dominators.end(), + std::inserter(result->data_dominators, result->data_dominators.end()), + location_ordert()); + + return result; + } + + return abstract_objectt::merge(other); +} + +/** + * Helper function for abstract_objectt::abstract_object_merge to perform any + * additional actions after the base abstract_object_merge has completed it's + * actions but immediately prior to it returning. As such, this function gives + * the ability to perform additional work for a merge. + * + * For the dependency context, this additional work is the tracking of + * last_written_locations across the merge + * + * \param other the object to merge with this + * + * \return the result of the merge + */ +abstract_object_pointert +data_dependency_contextt::abstract_object_merge_internal( + const abstract_object_pointert other) const +{ + auto other_context= + std::dynamic_pointer_cast(other); + + if(other_context) + { + const auto merged_parent = + std::dynamic_pointer_cast( + this->write_location_contextt::abstract_object_merge_internal(other)); + + return merged_parent->insert_data_deps(other_context->data_deps); + } + return shared_from_this(); +} + +/** + * Return the set of data dependencies associated with this node + * + * \return set of data dependencies + */ +std::set + data_dependency_contextt::get_data_dependencies() const +{ + std::set result; + for (const auto d : data_deps) result.insert(d); + return result; +} + +/** + * Return the set of data dominators associated with this node + * + * \return set of data dominators + */ +std::set + data_dependency_contextt::get_data_dominators() const +{ + std::set result; + for (const auto d : data_dominators) result.insert(d); + return result; +} + +void data_dependency_contextt::output( + std::ostream &out, const class ai_baset &ai, const namespacet &ns) const +{ + this->write_location_contextt::output(out, ai, ns); + + out << "[Data dependencies: "; + + bool comma = false; + for(auto d : data_deps) + { + out << (comma ? ", " : "") << d->location_number; + comma = true; + } + out << ']'; + + out << "[Data dominators: "; + + comma = false; + for(auto d : data_dominators) + { + out << (comma ? ", " : "") << d->location_number; + comma = true; + } + out << ']'; +} diff --git a/src/analyses/variable-sensitivity/data_dependency_context.h b/src/analyses/variable-sensitivity/data_dependency_context.h new file mode 100644 index 00000000000..5ef388c9c0e --- /dev/null +++ b/src/analyses/variable-sensitivity/data_dependency_context.h @@ -0,0 +1,113 @@ +/*******************************************************************\ + +Module: analyses variable-sensitivity data_dependency_context + +Author: Diffblue Ltd + +\*******************************************************************/ + +/** + * \file + * Maintain data dependencies as a context in the variable sensitivity domain + */ + +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_DATA_DEPENDENCY_CONTEXT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_DATA_DEPENDENCY_CONTEXT_H + +#include "variable_sensitivity_domain.h" +#include "write_location_context.h" + +class data_dependency_contextt: + public write_location_contextt { +public: + // These constructors mirror those in the base abstract_objectt, but with + // the addition of an extra argument which is the abstract_objectt to wrap. + explicit data_dependency_contextt( + const abstract_object_pointert child, + const typet &type): + write_location_contextt(child, type) + { + } + + data_dependency_contextt( + const abstract_object_pointert child, + const typet &type, + bool top, + bool bottom): + write_location_contextt(child, type, top, bottom) + { + } + + explicit data_dependency_contextt( + const abstract_object_pointert child, + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns): + write_location_contextt(child, expr, environment, ns) + { + } + + virtual abstract_object_pointert write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const override; + + virtual abstract_object_pointert update_location_context( + const abstract_objectt::locationst &locations, + const bool update_sub_elements) const override; + + bool has_been_modified(const abstract_object_pointert before) const override; + + std::set get_data_dependencies() const; + std::set get_data_dominators() const; + + virtual void output( + std::ostream &out, const class ai_baset &ai, const namespacet &ns) const + override; + +protected: + CLONE + + virtual abstract_object_pointert merge( + abstract_object_pointert other) const override; + + virtual abstract_object_pointert abstract_object_merge_internal( + const abstract_object_pointert other) const override; + + +private: + class location_ordert + { + public: + bool operator()( + goto_programt::const_targett instruction, + goto_programt::const_targett other_instruction) + { + return instruction->location_number> + other_instruction->location_number; + } + }; + typedef std::set dependencest; + dependencest data_deps; + dependencest data_dominators; + + abstract_object_pointert insert_data_deps( + const dependencest &dependencies) const; + + abstract_object_pointert insert_data_deps(const locationst &locations) const + { + // `locationst` is unsorted, so convert this to a sorted `dependenciest` + dependencest dependencies; + + for(const auto l : locations) + dependencies.insert(l); + + return insert_data_deps(dependencies); + } + +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_DATA_DEPENDENCY_CONTEXT_H diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 0a1ce1fd315..3f37a57e2af 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -100,46 +100,36 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: switch(abstract_object_type) { case CONSTANT: - return initialize_abstract_object< - typed_write_location_contextt>( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); case ARRAY_SENSITIVE: - return initialize_abstract_object< - typed_write_location_contextt>( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); case ARRAY_INSENSITIVE: - return initialize_abstract_object< - typed_write_location_contextt>( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); case POINTER_SENSITIVE: - return initialize_abstract_object< - typed_write_location_contextt>( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); case POINTER_INSENSITIVE: - return initialize_abstract_object< - typed_write_location_contextt>( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); case STRUCT_SENSITIVE: - return initialize_abstract_object< - typed_write_location_contextt>( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); case STRUCT_INSENSITIVE: - return initialize_abstract_object< - typed_write_location_contextt>( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); case UNION_INSENSITIVE: - return initialize_abstract_object< - typed_write_location_contextt>( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); case TWO_VALUE: - return initialize_abstract_object< - typed_write_location_contextt>( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); default: UNREACHABLE; - return initialize_abstract_object< - typed_write_location_contextt>( - followed_type, top, bottom, e, environment, ns); + return initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); } } @@ -163,5 +153,8 @@ void variable_sensitivity_object_factoryt::set_options(const optionst &options) has_structs_flag=options.get_bool_option("structs"); has_arrays_flag=options.get_bool_option("arrays"); has_pointers_flag=options.get_bool_option("pointers"); + has_last_written_location_context_flag=true; // For efficency of 3way merge + has_data_dependencies_context_flag= + options.get_bool_option("data-dependencies"); 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 e34118e19d9..be1542b118b 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -16,7 +16,9 @@ #include #include #include +#include #include +#include #include #include @@ -63,10 +65,20 @@ class variable_sensitivity_object_factoryt const exprt &e, const abstract_environmentt &enviroment, const namespacet &ns); + template + abstract_object_pointert initialize_context_abstract_object( + 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; bool has_arrays_flag; bool has_pointers_flag; + bool has_last_written_location_context_flag; + bool has_data_dependencies_context_flag; bool initialized; }; @@ -98,17 +110,47 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: const exprt &e, const abstract_environmentt &enviroment, const namespacet &ns) +{ + if(has_data_dependencies_context_flag) + return initialize_context_abstract_object< + abstract_object_classt, data_dependency_contextt>( + type, top, bottom, e, enviroment, ns); + if(has_last_written_location_context_flag) + return initialize_context_abstract_object< + abstract_object_classt, write_location_contextt>( + type, top, bottom, e, enviroment, ns); + else + return initialize_context_abstract_object< + abstract_object_classt, context_abstract_objectt>( + type, top, bottom, e, enviroment, ns); +} + +template +abstract_object_pointert variable_sensitivity_object_factoryt:: + initialize_context_abstract_object( + const typet type, + bool top, + bool bottom, + const exprt &e, + const abstract_environmentt &enviroment, + const namespacet &ns) { if(top || bottom) { return abstract_object_pointert( - new abstract_object_classt(type, top, bottom)); + new context_classt( + abstract_object_pointert( + new abstract_object_classt(type, top, bottom)), + type, top, bottom)); } else { PRECONDITION(type==ns.follow(e.type())); return abstract_object_pointert( - new abstract_object_classt(e, enviroment, ns)); + new context_classt( + abstract_object_pointert( + new abstract_object_classt(e, enviroment, ns)), + e, enviroment, ns)); } } diff --git a/src/analyses/variable-sensitivity/write_location_context.h b/src/analyses/variable-sensitivity/write_location_context.h index 23c874530d8..1c861960c7f 100644 --- a/src/analyses/variable-sensitivity/write_location_context.h +++ b/src/analyses/variable-sensitivity/write_location_context.h @@ -120,38 +120,4 @@ class write_location_contextt: public context_abstract_objectt const abstract_objectt::locationst &locations); }; -/** - * Templated extension of the abstract implementation, used as a wrapper around - * other abstract_objectt classes to enable the factory to instantiate the - * context information - */ -template -class typed_write_location_contextt: public write_location_contextt -{ -public: - explicit typed_write_location_contextt(const typet &type): - write_location_contextt( - abstract_object_pointert(new AOT(type)), type) {} - - typed_write_location_contextt( - const typet &type, - bool top, - bool bottom): - write_location_contextt( - abstract_object_pointert(new AOT(type, top, bottom)), - type, - top, - bottom) {} - - explicit typed_write_location_contextt( - const exprt &expr, - const abstract_environmentt &environment, - const namespacet &ns): - write_location_contextt( - abstract_object_pointert(new AOT(expr, environment, ns)), - expr, - environment, - ns) {} -}; - #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_LOCATION_CONTEXT_H From 9332c86f40eac11425ccdef9cd79027bffa2138b Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Tue, 24 Apr 2018 16:52:58 +0100 Subject: [PATCH 211/342] Add variable sensitivity data dependency graph --- .../file1.c | 22 ++ .../file2.c | 16 ++ .../main.c | 60 ++++++ .../test.desc | 37 ++++ .../variable_sensitivity_dependence_graph.cpp | 191 ++++++++++++++++++ .../variable_sensitivity_dependence_graph.h | 66 ++++++ .../variable_sensitivity_domain.h | 7 + 7 files changed, 399 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph/file1.c create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph/file2.c create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc create mode 100644 src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp create mode 100644 src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/file1.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph/file1.c new file mode 100644 index 00000000000..b69b7a06662 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/file1.c @@ -0,0 +1,22 @@ +struct structt { + int a; + int b; +}; + +extern struct structt st; +extern int in; +int out1, out2, out3; + +void struct_task(void) +{ + int i; + if (in == 1) + st.a++; + + if (in == 2) + st.b++; + + out1 = st.a; + out2 = st.b; + out3 = st.a + st.b; +} diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/file2.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph/file2.c new file mode 100644 index 00000000000..2a02b6b5e31 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/file2.c @@ -0,0 +1,16 @@ +extern int ar[2]; +extern int in; +int out1, out2, out3; + +void array_task(void) +{ + if (in == 1) + ar[0]++; + + if (in == 2) + ar[1]++; + + out1 = ar[0]; + out2 = ar[1]; + out3 = ar[0] + ar[1]; +} diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/main.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph/main.c new file mode 100644 index 00000000000..a92b484de5a --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/main.c @@ -0,0 +1,60 @@ +struct structt { + int a; + int b; +}; + +struct structt st; +int ar[2]; +int arr[3]; + +extern int in; +int out1, out2, out3; + +void struct_task(void); +void array_task(void); + +void main(void) +{ + if (in == 1) + st.a++; + + if (in == 2) + st.b++; + + out1 = st.a; + out2 = st.b; + out3 = st.a + st.b; + + if (in == 1) + ar[0]++; + + if (in == 2) + ar[1]++; + + out1 = ar[0]; + out2 = ar[1]; + out3 = ar[0] + ar[1]; + + arr[0] = 1; + arr[1] = 2; + arr[2] = 3; + + if (in > 0) + { + arr[2] = arr[1]; + } + + out1 = arr[0]; + out2 = arr[1]; + out3 = arr[2]; + + struct_task(); + out1 = st.a; + out2 = st.b; + out3 = st.a + st.b; + + array_task(); + out1 = ar[0]; + out2 = ar[1]; + out3 = ar[0] + ar[1]; +} diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc new file mode 100644 index 00000000000..a10dceacd95 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc @@ -0,0 +1,37 @@ +CORE +main.c +file1.c file2.c --dependence-graph-vs --structs --arrays --show +EXIT=0 +SIGNAL=0 +^Data dependencies: 53$ +^Data dependencies: 53$ +^Data dependencies: 1, 53$ +^Data dependencies: 4, 53$ +^Data dependencies: 1, 4, 53$ +^Data dependencies: 48$ +^Data dependencies: 48$ +^Data dependencies: 10, 48$ +^Data dependencies: 13, 48$ +^Data dependencies: 10, 13, 48$ +^Data dependencies: 19$ +^Data dependencies: 18$ +^Data dependencies: 19$ +^Data dependencies: 19, 20, 22$ +^Data dependencies: 1, 53, 57$ +^Data dependencies: 4, 53, 60$ +^Data dependencies: 1, 4, 53, 57, 60$ +^Data dependencies: 10, 48, 68$ +^Data dependencies: 13, 48, 71$ +^Data dependencies: 10, 13, 48, 68, 71$ +^Data dependencies: 1, 53$ +^Data dependencies: 4, 53$ +^Data dependencies: 1, 53, 57$ +^Data dependencies: 4, 53, 60$ +^Data dependencies: 1, 4, 53, 57, 60$ +^Data dependencies: 10, 48$ +^Data dependencies: 13, 48$ +^Data dependencies: 10, 48, 68$ +^Data dependencies: 13, 48, 71$ +^Data dependencies: 10, 13, 48, 68, 71$ +-- +^warning: ignoring diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp new file mode 100644 index 00000000000..9e779c27aef --- /dev/null +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -0,0 +1,191 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity variable-sensitivity-dependence-graph + + Author: Diffblue Ltd. + +\*******************************************************************/ + +#include "data_dependency_context.h" +#include "variable_sensitivity_dependence_graph.h" + +#include +#include +#include + + +/** + * Evaluate an expression and accumulate all the data dependencies + * involved in the evaluation. + * + * \param expr the expression to evaluate + * \param ns the namespace to use + * \param deps the destination in which to accumlate data dependencies + */ +void variable_sensitivity_dependence_grapht::eval_data_deps( + const exprt &expr, const namespacet &ns, data_depst &deps) const +{ + const auto res= + std::dynamic_pointer_cast(eval(expr, ns)); + + if(res->get_data_dependencies().size() > 0) + { + // If the expression was able to be eval'ed to something with data + // dependencies, then that's all we need to gather. + for (const auto dep : res->get_data_dependencies()) + deps.insert(dep); + } + else + { + // If the expression could not be eval'ed to somethign with data + // dependencies, then it may have been some sort of compound expression, + // so attempt to eval the data dependencies for all the operands, taking + // the union of them all. + for(const exprt &op : expr.operands()) + { + eval_data_deps(op, ns, deps); + } + } +} + +/** + * Compute the abstract transformer for a single instruction. For + * the data dependencies, this involves calculating all the data + * dependencies that exist in the 'to' instruction. + * + * \param from the instruction before the abstract domain + * \param to the instruction after the abstract domain + * \param ai the abstract interpreter + * \param ns the namespace + */ +void variable_sensitivity_dependence_grapht::transform( + locationt from, + locationt to, + ai_baset &ai, + const namespacet &ns) +{ + variable_sensitivity_domaint::transform(from, to, ai, ns); + + // Find all the data dependencies in the the 'to' expression + domain_data_deps.clear(); + if(to->is_assign()) + { + const code_assignt &inst = to_code_assign(to->code); + + eval_data_deps(inst.rhs(), ns, domain_data_deps); + } +} + +/** + * Computes the join between "this" and "b" + * + * \param b the other domain + * \param from the location preceding the 'b' domain + * \param to the current location + * \return true if something has changed in the merge + */ +bool variable_sensitivity_dependence_grapht::merge( + const variable_sensitivity_domaint &b, + locationt from, + locationt to) +{ + bool changed = false; + + changed = variable_sensitivity_domaint::merge(b, from, to); + + const auto cast_b = + dynamic_cast(b); + + for (auto bdep : cast_b.domain_data_deps) + { + auto result = domain_data_deps.insert(bdep); + changed |= result.second; + } + + return changed; +} + +/** + * Perform a context aware merge of the changes that have been applied + * between function_start and the current state. Anything that has not been + * modified will be taken from the \p function_call domain. + * + * \param function_call: The local of the merge - values from here will be + * taken if they have not been modified + * \param function_start: THe base of the merge - changes that have been made + * between here and this will be retained. + * \param ns: The global namespace + */ +void variable_sensitivity_dependence_grapht::merge_three_way_function_return( + const ai_domain_baset &function_call, + const ai_domain_baset &function_start, + const ai_domain_baset &function_end, + const namespacet &ns) +{ + // The gathering of the data dependencies for the domain is handled by the + // 'transform' and simply relies on the underlying domains with their + // data_dependency_context to be correct. Therefore all we need to ensure at + // the three way merge is that the underlying variable senstivitiy domain + // does it's three way merge. + variable_sensitivity_domaint::merge_three_way_function_return( + function_call, + function_start, + function_end, + ns); +} + +/** + * Basic text output of the abstract domain + * + * \param out the stream to output onto + * \param ai the abstract domain + * \param ns the namespace + */ +void variable_sensitivity_dependence_grapht::output( + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const +{ + if(!domain_data_deps.empty()) + { + out << "Data dependencies: "; + bool first = true; + for (auto &dep : domain_data_deps) + { + if(!first) + out << ", "; + + out << dep->location_number; + + first = false; + } + out << std::endl; + } +} + +/** + * \brief Outputs the current value of the domain. + * + * \param ai the abstract interpreter + * \param ns the namespace + * + * \return the domain, formatted as a JSON object. + */ +jsont variable_sensitivity_dependence_grapht::output_json( + const ai_baset &ai, + const namespacet &ns) const +{ + json_arrayt graph; + + for(const auto &dep : domain_data_deps) + { + json_objectt &link=graph.push_back().make_object(); + link["locationNumber"]= + json_numbert(std::to_string(dep->location_number)); + link["sourceLocation"]=json(dep->source_location); + json_stringt(dep->source_location.as_string()); + link["type"]=json_stringt("data"); + } + + return graph; +} diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h new file mode 100644 index 00000000000..58c56b1d9e7 --- /dev/null +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -0,0 +1,66 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity variable-sensitivity-dependence-graph + + Author: Diffblue Ltd. + +\*******************************************************************/ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DEPENDENCE_GRAPH_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DEPENDENCE_GRAPH_H + +#include "variable_sensitivity_domain.h" + +#include + +class variable_sensitivity_dependence_grapht: + public variable_sensitivity_domaint +{ +public: + + void transform( + locationt from, + locationt to, + ai_baset &ai, + const namespacet &ns) override; + + virtual bool merge( + const variable_sensitivity_domaint &b, + locationt from, + locationt to) override; + + virtual void merge_three_way_function_return( + const ai_domain_baset &function_call, + const ai_domain_baset &function_start, + const ai_domain_baset &function_end, + const namespacet &ns) override; + + + void output( + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const override; + + jsont output_json( + const ai_baset &ai, + const namespacet &ns) const override; + +private: + class dependency_ordert + { + public: + bool operator()( + const goto_programt::const_targett &a, + const goto_programt::const_targett &b) const + { + return a->location_number < b->location_number; + } + }; + typedef std::set data_depst; + data_depst domain_data_deps; + + void eval_data_deps( + const exprt &expr, const namespacet &ns, data_depst &deps) const; +}; + +// NOLINTNEXTLINE(whitespace/line_length) +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DEPENDENCE_GRAPH_H diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index e7d0983d600..9a755869b9b 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -112,6 +112,13 @@ class variable_sensitivity_domaint:public ai_domain_baset bool is_bottom() const override; bool is_top() const override; +protected: + virtual abstract_object_pointert eval( + const exprt &expr, const namespacet &ns) const + { + return abstract_state.eval(expr, ns); + } + private: void transform_function_call( locationt from, From 53705fa543ace9d28cb799904c071d73e5b5a7c5 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 25 Apr 2018 16:01:00 +0100 Subject: [PATCH 212/342] [DO NOT MERGE] Track which expressions give rise to data dependencies This is a customer special feature which tracks which expressions are the source of any data dependencies, displaying those expressions as part of the output. JSON output also includes the 'certainty' level of the dependency. At the moment, this is a hard coded/enabled feature. It should be made controlled by a command line option before it gets considered for merging, but PR'ing anyway for review comments. --- .../file1.c | 22 +++++++ .../file2.c | 16 +++++ .../main.c | 60 +++++++++++++++++++ .../test.desc | 37 ++++++++++++ .../variable_sensitivity_dependence_graph.cpp | 40 ++++++++++--- .../variable_sensitivity_dependence_graph.h | 2 +- 6 files changed, 168 insertions(+), 9 deletions(-) create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/file1.c create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/file2.c create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/file1.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/file1.c new file mode 100644 index 00000000000..b69b7a06662 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/file1.c @@ -0,0 +1,22 @@ +struct structt { + int a; + int b; +}; + +extern struct structt st; +extern int in; +int out1, out2, out3; + +void struct_task(void) +{ + int i; + if (in == 1) + st.a++; + + if (in == 2) + st.b++; + + out1 = st.a; + out2 = st.b; + out3 = st.a + st.b; +} diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/file2.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/file2.c new file mode 100644 index 00000000000..2a02b6b5e31 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/file2.c @@ -0,0 +1,16 @@ +extern int ar[2]; +extern int in; +int out1, out2, out3; + +void array_task(void) +{ + if (in == 1) + ar[0]++; + + if (in == 2) + ar[1]++; + + out1 = ar[0]; + out2 = ar[1]; + out3 = ar[0] + ar[1]; +} diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/main.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/main.c new file mode 100644 index 00000000000..a92b484de5a --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/main.c @@ -0,0 +1,60 @@ +struct structt { + int a; + int b; +}; + +struct structt st; +int ar[2]; +int arr[3]; + +extern int in; +int out1, out2, out3; + +void struct_task(void); +void array_task(void); + +void main(void) +{ + if (in == 1) + st.a++; + + if (in == 2) + st.b++; + + out1 = st.a; + out2 = st.b; + out3 = st.a + st.b; + + if (in == 1) + ar[0]++; + + if (in == 2) + ar[1]++; + + out1 = ar[0]; + out2 = ar[1]; + out3 = ar[0] + ar[1]; + + arr[0] = 1; + arr[1] = 2; + arr[2] = 3; + + if (in > 0) + { + arr[2] = arr[1]; + } + + out1 = arr[0]; + out2 = arr[1]; + out3 = arr[2]; + + struct_task(); + out1 = st.a; + out2 = st.b; + out3 = st.a + st.b; + + array_task(); + out1 = ar[0]; + out2 = ar[1]; + out3 = ar[0] + ar[1]; +} diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc new file mode 100644 index 00000000000..614e1f078f9 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc @@ -0,0 +1,37 @@ +CORE +main.c +file1.c file2.c --dependence-graph-vs --structs --arrays --show +EXIT=0 +SIGNAL=0 +Data dependencies: 53 \[st.a\] +Data dependencies: 53 \[st.b\] +Data dependencies: 1 \[st.a\], 53 \[st.a\] +Data dependencies: 4 \[st.b\], 53 \[st.b\] +Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\] +Data dependencies: 48 \[ar\[\(signed long int\)0\]\] +Data dependencies: 48 \[ar\[\(signed long int\)1\]\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\] +Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\] +Data dependencies: 19 \[arr\[\(signed long int\)1\]\] +Data dependencies: 18 \[arr\[\(signed long int\)0\]\] +Data dependencies: 19 \[arr\[\(signed long int\)1\]\] +Data dependencies: 19 \[arr\[\(signed long int\)2\]\], 20 \[arr\[\(signed long int\)2\]\], 22 \[arr\[\(signed long int\)2\]\] +Data dependencies: 1 \[st.a\], 53 \[st.a\], 57 \[st.a\] +Data dependencies: 4 \[st.b\], 53 \[st.b\], 60 \[st.b\] +Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\], 57 \[st.a\], 60 \[st.b\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\], 68 \[ar\[\(signed long int\)0\]\] +Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\], 71 \[ar\[\(signed long int\)1\]\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 68 \[ar\[\(signed long int\)0\]\], 71 \[ar\[\(signed long int\)1\]\] +Data dependencies: 1 \[st.a\], 53 \[st.a\] +Data dependencies: 4 \[st.b\], 53 \[st.b\] +Data dependencies: 1 \[st.a\], 53 \[st.a\], 57 \[st.a\] +Data dependencies: 4 \[st.b\], 53 \[st.b\], 60 \[st.b\] +Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\], 57 \[st.a\], 60 \[st.b\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\] +Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\], 68 \[ar\[\(signed long int\)0\]\] +Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\], 71 \[ar\[\(signed long int\)1\]\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 68 \[ar\[\(signed long int\)0\]\], 71 \[ar\[\(signed long int\)1\]\] +-- +^warning: ignoring diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index 9e779c27aef..1a0be8336be 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -33,11 +33,11 @@ void variable_sensitivity_dependence_grapht::eval_data_deps( // If the expression was able to be eval'ed to something with data // dependencies, then that's all we need to gather. for (const auto dep : res->get_data_dependencies()) - deps.insert(dep); + deps[dep].insert(expr); } else { - // If the expression could not be eval'ed to somethign with data + // If the expression could not be eval'ed to something with data // dependencies, then it may have been some sort of compound expression, // so attempt to eval the data dependencies for all the operands, taking // the union of them all. @@ -98,8 +98,11 @@ bool variable_sensitivity_dependence_grapht::merge( for (auto bdep : cast_b.domain_data_deps) { - auto result = domain_data_deps.insert(bdep); - changed |= result.second; + for(exprt bexpr : bdep.second) + { + auto result = domain_data_deps[bdep.first].insert(bexpr); + changed |= result.second; + } } return changed; @@ -155,7 +158,18 @@ void variable_sensitivity_dependence_grapht::output( if(!first) out << ", "; - out << dep->location_number; + out << dep.first->location_number; + out << " ["; + bool first_expr = true; + for (auto &expr : dep.second) + { + if (!first_expr) + out << ", "; + + out << from_expr(ns, "", expr); + first_expr = false; + } + out << "]"; first = false; } @@ -181,10 +195,20 @@ jsont variable_sensitivity_dependence_grapht::output_json( { json_objectt &link=graph.push_back().make_object(); link["locationNumber"]= - json_numbert(std::to_string(dep->location_number)); - link["sourceLocation"]=json(dep->source_location); - json_stringt(dep->source_location.as_string()); + json_numbert(std::to_string(dep.first->location_number)); + link["sourceLocation"]=json(dep.first->source_location); + json_stringt(dep.first->source_location.as_string()); link["type"]=json_stringt("data"); + + const std::set &expr_set=dep.second; + json_arrayt &expressions=link["expressions"].make_array(); + + for(const exprt &e : expr_set) + { + json_objectt &object=expressions.push_back().make_object(); + object["expression"]=json_stringt(from_expr(ns, "", e)); + object["certainty"]=json_stringt("maybe"); + } } return graph; diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h index 58c56b1d9e7..dabc3a227b4 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -55,7 +55,7 @@ class variable_sensitivity_dependence_grapht: return a->location_number < b->location_number; } }; - typedef std::set data_depst; + typedef std::map, dependency_ordert> data_depst; data_depst domain_data_deps; void eval_data_deps( From b4dbd08335ba5b06f4c5f87c97ab63b2ac0d5001 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Mon, 30 Apr 2018 14:24:49 +0100 Subject: [PATCH 213/342] Avoid breaking sharing in usage of sharing_mapt in full_struct_abstract_object --- .../full_struct_abstract_object.cpp | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index b0dc3c3c82a..372d3df487b 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -228,15 +228,17 @@ sharing_ptrt starting_value= environment.abstract_object_factory( member_expr.type(), ns, true, false); + result->map.insert( + c, + environment.write(starting_value, value, stack, ns, merging_write), + tvt(false)); } else { - starting_value=old_value.first; + result->map.find(c, tvt(true)).first = + environment.write(old_value.first, value, stack, ns, merging_write); } - result->map[c] = - environment.write(starting_value, value, stack, ns, merging_write); - result->clear_top(); DATA_INVARIANT(result->verify(), "Structural invariants maintained"); return result; @@ -249,6 +251,7 @@ sharing_ptrt #endif const irep_idt c=member_expr.get_component_name(); + shared_struct_mapt::const_find_type old_value=result->map.find(c); if(merging_write) { @@ -260,8 +263,6 @@ sharing_ptrt INVARIANT(!result->map.empty(), "If not top, map cannot be empty"); - shared_struct_mapt::const_find_type old_value=result->map.find(c); - if(!old_value.second) // component is top { DATA_INVARIANT(result->verify(), "Structural invariants maintained"); @@ -270,11 +271,19 @@ sharing_ptrt bool dummy; - result->map[c] = abstract_objectt::merge(old_value.first, value, dummy); + result->map.find(c, tvt(true)).first = + abstract_objectt::merge(old_value.first, value, dummy); } else { - result->map[c] = value; + if(old_value.second) + { + result->map.find(c, tvt(true)).first = value; + } + else + { + result->map.insert(c, value, tvt(false)); + } result->clear_top(); INVARIANT(!result->is_bottom(), "top != bottom"); } @@ -456,7 +465,7 @@ abstract_object_pointert full_struct_abstract_objectt::visit_sub_elements( auto newval = visitor.visit(item.second); if(newval != item.second) { - result->map[item.first] = newval; + result->map.find(item.first, tvt(true)).first = newval; modified = true; } } From 6433744d1315fc453ebfcc5f2977dfee2a5c8b4a Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Mon, 30 Apr 2018 14:55:36 +0100 Subject: [PATCH 214/342] Avoid breaking sharing in usage of sharing_mapt in constant_array_abstract_object --- .../constant_array_abstract_object.cpp | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index bb365371129..19972c96a40 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -82,7 +82,10 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( int index=0; for(const exprt &entry : expr.operands()) { - map[mp_integer(index)]=environment.eval(entry, ns); + map.insert( + mp_integer(index), + environment.eval(entry, ns), + tvt(false)); ++index; } clear_top(); @@ -329,21 +332,22 @@ sharing_ptrt { // We were able to evaluate the index to a value, which we // assume is in bounds... - abstract_object_pointert starting_value; shared_array_mapt::const_find_type old_value = map.find(index_value); if(!old_value.second) { - starting_value=get_top_entry(environment, ns); + result->map.insert( + index_value, + environment.write( + get_top_entry(environment, ns), value, stack, ns, merging_write), + tvt(false)); } else { - starting_value=old_value.first; + result->map.find(index_value, tvt(true)).first = + environment.write(old_value.first, value, stack, ns, merging_write); } - result->map[index_value] = - environment.write(starting_value, value, stack, ns, merging_write); - result->clear_top(); DATA_INVARIANT(result->verify(), "Structural invariants maintained"); return result; @@ -357,9 +361,9 @@ sharing_ptrt for(const auto &starting_value : view) { // Merging write since we don't know which index we are writing to - result->map[starting_value.first]= - environment.write( - starting_value.second, value, stack, ns, true); + result->map.find(starting_value.first, tvt(true)).first = + environment.write(starting_value.second, value, stack, ns, true); + result->clear_top(); } @@ -383,7 +387,7 @@ sharing_ptrt } INVARIANT(!result->map.empty(), "If not top, map cannot be empty"); - + shared_array_mapt::const_find_type old_value= result->map.find(index_value); @@ -395,7 +399,7 @@ sharing_ptrt bool dummy; - result->map[index_value] = + result->map.find(index_value, tvt(true)).first = abstract_objectt::merge(old_value.first, value, dummy); DATA_INVARIANT(result->verify(), "Structural invariants maintained"); @@ -403,7 +407,19 @@ sharing_ptrt } else { - result->map[index_value] = value; + shared_array_mapt::find_type old_value= + result->map.find(index_value); + if(old_value.second) + { + if(value != old_value.first) + { + old_value.first = value; + } + } + else + { + result->map.insert(index_value, value, tvt(false)); + } result->clear_top(); DATA_INVARIANT(result->verify(), "Structural invariants maintained"); return result; @@ -502,9 +518,9 @@ constant_array_abstract_objectt::visit_sub_elements( auto newval = visitor.visit(item.second); if(newval != item.second) { - result->map[item.first]=newval; + result->map.find(item.first, tvt(true)).first = newval; modified = true; - } + } } if(modified) From c8928fc43883a5c94a1257514e4b69386afce9c7 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Thu, 10 May 2018 15:44:38 +0100 Subject: [PATCH 215/342] Add data dependency context and variable sensitivity dependence graph to Makefile --- src/analyses/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyses/Makefile b/src/analyses/Makefile index 7b9d30abecf..53bdc61f3c5 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -50,6 +50,8 @@ SRC = ai.cpp \ variable-sensitivity/union_abstract_object.cpp \ variable-sensitivity/write_stack.cpp \ variable-sensitivity/write_stack_entry.cpp \ + variable-sensitivity/data_dependency_context.cpp \ + variable-sensitivity/variable_sensitivity_dependence_graph.cpp \ # Empty last line INCLUDES= -I .. From 29b1b80531fbf88e5a3167ad45e7cb8eb893fa26 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Thu, 10 May 2018 16:07:17 +0100 Subject: [PATCH 216/342] Remove stray ; in context abstract object --- src/analyses/variable-sensitivity/context_abstract_object.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/context_abstract_object.cpp b/src/analyses/variable-sensitivity/context_abstract_object.cpp index cb7c3140b88..7f4a3592533 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/context_abstract_object.cpp @@ -145,4 +145,4 @@ bool context_abstract_objectt::has_been_modified( return this->child_abstract_object.get() != before_context->child_abstract_object.get(); -}; +} From 50a71775f5019b026f62703679b7167106846744 Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 11:23:41 +0000 Subject: [PATCH 217/342] Interval values --- .../variable-sensitivity/abstract_object.h | 2 +- .../interval_abstract_value.cpp | 172 ++++++++++++++++++ .../interval_abstract_value.h | 74 ++++++++ .../variable_sensitivity_object_factory.cpp | 6 +- .../variable_sensitivity_object_factory.h | 3 + 5 files changed, 255 insertions(+), 2 deletions(-) create mode 100644 src/analyses/variable-sensitivity/interval_abstract_value.cpp create mode 100644 src/analyses/variable-sensitivity/interval_abstract_value.h diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index c3316c2ffec..6bf9d5c8b5b 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -93,7 +93,7 @@ class abstract_objectt:public std::enable_shared_from_this virtual bool is_bottom() const; // Interface for transforms - abstract_object_pointert expression_transform( + virtual abstract_object_pointert expression_transform( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns) const; diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp new file mode 100644 index 00000000000..c3aed5a5efd --- /dev/null +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -0,0 +1,172 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ + +#include + +#include +#include + +#include "abstract_enviroment.h" + +#include "interval_abstract_value.h" + +interval_abstract_valuet::interval_abstract_valuet(typet t): + abstract_valuet(t), interval() +{} + +interval_abstract_valuet::interval_abstract_valuet(typet t, bool tp, bool bttm): + abstract_valuet(t, tp, bttm), interval() +{} + +interval_abstract_valuet::interval_abstract_valuet( + const constant_interval_exprt e): + abstract_valuet(e.type(), false, false), interval(e) +{ + +} + +exprt interval_abstract_valuet::to_constant() const +{ + if(!is_top() && !is_bottom()) + { + return this->interval; + } + else + { + return abstract_objectt::to_constant(); + } +} + +#if 1 +// Interface for transforms +abstract_object_pointert interval_abstract_valuet::expression_transform( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const +{ + if(expr.id() == ID_constant_interval) + { + return environment.abstract_object_factory(expr.type(), expr, ns); + } + else + { + return abstract_objectt::expression_transform(expr, environment, ns); + } +} +#endif + +void interval_abstract_valuet::output( + std::ostream &out, const ai_baset &ai, const namespacet &ns) const +{ + if(!is_top() && !is_bottom()) + { + std::string lower_string; + std::string upper_string; + + if(interval.get_lower().id() == ID_min) { + lower_string = "-INF"; + } else { + INVARIANT(interval.get_lower().id() == ID_constant, + "We only support constant limits"); + lower_string = id2string(to_constant_expr(interval.get_lower()).get_value()); + } + + if(interval.get_upper().id() == ID_max) { + upper_string = "+INF"; + } else { + INVARIANT(interval.get_lower().id() == ID_constant, + "We only support constant limits"); + upper_string = id2string(to_constant_expr(interval.get_upper()).get_value()); + } + + out << "[" << lower_string << ", " << upper_string << "]"; + } + else + { + abstract_objectt::output(out, ai, ns); + } +} + +/*******************************************************************\ + +Function: interval_abstract_valuet::merge + + Inputs: + other - the abstract object to merge with + + Outputs: Returns the result of the merge + + Purpose: Attempts to do a interval/interval merge if both are intervals, + otherwise falls back to the parent merge + + +\*******************************************************************/ + +abstract_object_pointert interval_abstract_valuet::merge( + abstract_object_pointert other) const +{ + interval_abstract_value_pointert cast_other= + std::dynamic_pointer_cast(other); + if(cast_other) + { + return merge_interval_interval(cast_other); + } + else + { + // TODO(tkiley): How do we set the result to be toppish? Does it matter? + return abstract_valuet::merge(other); + } +} + +/*******************************************************************\ + +Function: interval_abstract_valuet::merge_interval_interval + + Inputs: + other - the abstract object to merge with + + 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 interval abstract value into this one + +\*******************************************************************/ + +abstract_object_pointert interval_abstract_valuet::merge_interval_interval( + interval_abstract_value_pointert other) const +{ + if(is_bottom() || other->interval.contains(interval)) + { + return other; + } + else if(other->is_bottom() || interval.contains(other->interval)) + { + return shared_from_this(); + } + else + { + return std::make_shared( + constant_interval_exprt( + constant_interval_exprt::get_min(interval.get_lower(), other->interval.get_lower()), + constant_interval_exprt::get_max(interval.get_upper(), other->interval.get_upper()))); + } + +#if 0 + // Can we actually merge these value + if(value==other->value) + { + return shared_from_this(); + } + else + { + return abstract_valuet::merge(other); + } + } +#endif +} diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h new file mode 100644 index 00000000000..60857c2ab95 --- /dev/null +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -0,0 +1,74 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: Thomas Kiley, thomas.kiley@diffblue.com + +\*******************************************************************/ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_INTERVAL_ABSTRACT_VALUE_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_INTERVAL_ABSTRACT_VALUE_H + +#include + +#include + +#include +#include + +class interval_abstract_valuet:public abstract_valuet +{ +private: + typedef sharing_ptrt + interval_abstract_value_pointert; + static inline constant_interval_exprt make_interval_expr(exprt e) { + if(e.id() == ID_constant_interval) { + return to_constant_interval_expr(e); + } else { + return constant_interval_exprt(e, e); + } + } +public: + explicit interval_abstract_valuet(typet t); + interval_abstract_valuet(typet t, bool tp, bool bttm); + interval_abstract_valuet( + const constant_interval_exprt e); + interval_abstract_valuet( + const exprt e, + const abstract_environmentt &environment, + const namespacet &ns) + : interval_abstract_valuet(make_interval_expr(e)) + { + + } + + virtual ~interval_abstract_valuet() {} + + virtual exprt to_constant() const override; + +#if 1 + // Interface for transforms + abstract_object_pointert expression_transform( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const override; +#endif + + virtual void output( + std::ostream &out, + const class ai_baset &ai, + const class namespacet &ns) const override; + +protected: + CLONE + virtual abstract_object_pointert merge( + abstract_object_pointert other) const override; + +private : + abstract_object_pointert merge_interval_interval( + interval_abstract_value_pointert other) const; + + constant_interval_exprt interval; + //exprt value; +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_INTERVAL_ABSTRACT_VALUE_H diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 3f37a57e2af..fa19566956e 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -35,7 +35,7 @@ variable_sensitivity_object_factoryt::ABSTRACT_OBJECT_TYPET type.id()==ID_c_bool || type.id()==ID_bool || type.id()==ID_integer || type.id()==ID_c_bit_field) { - abstract_object_type=CONSTANT; + abstract_object_type=has_interval?INTERVAL:CONSTANT; } else if(type.id()==ID_array) { @@ -102,6 +102,9 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: case CONSTANT: return initialize_abstract_object( followed_type, top, bottom, e, environment, ns); + case INTERVAL: + return initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); case ARRAY_SENSITIVE: return initialize_abstract_object( followed_type, top, bottom, e, environment, ns); @@ -156,5 +159,6 @@ void variable_sensitivity_object_factoryt::set_options(const optionst &options) has_last_written_location_context_flag=true; // For efficency of 3way merge has_data_dependencies_context_flag= options.get_bool_option("data-dependencies"); + has_interval=options.get_bool_option("interval"); 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 be1542b118b..c2c0f40f576 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -9,6 +9,7 @@ #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_OBJECT_FACTORY_H #include +#include #include #include #include @@ -47,6 +48,7 @@ class variable_sensitivity_object_factoryt { TWO_VALUE, CONSTANT, + INTERVAL, ARRAY_SENSITIVE, ARRAY_INSENSITIVE, POINTER_SENSITIVE, @@ -79,6 +81,7 @@ class variable_sensitivity_object_factoryt bool has_pointers_flag; bool has_last_written_location_context_flag; bool has_data_dependencies_context_flag; + bool has_interval; bool initialized; }; From 8b5ee16863763aa50e98d33ce114a09d2c58e7d9 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Thu, 10 May 2018 13:12:40 +0100 Subject: [PATCH 218/342] Add regression tests for interval abstract values --- .../main.c | 36 +++++++++++++++++++ .../test.desc | 11 ++++++ .../main.c | 19 ++++++++++ .../test.desc | 11 ++++++ .../main.c | 19 ++++++++++ .../test.desc | 11 ++++++ 6 files changed, 107 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-float/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-float/test.desc create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/main.c new file mode 100644 index 00000000000..f3710813803 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/main.c @@ -0,0 +1,36 @@ +#include +#include + +struct Vec2 { + int x; + int y; +}; + +void MakeZero(struct Vec2 *vec) { + vec->x = 0; + vec->y = 0; +} + +void MakeOne(struct Vec2 *vec) { + vec->x = 1; + vec->y = 1; +} + +int main(void) +{ + struct Vec2 vec = {-10, 10}; + struct Vec2 vecMinusTenAndTen = vec; + int nondet_condition; + if(nondet_condition) { + MakeZero(&vec); + struct Vec2 vecZero = vec; + } else { + MakeOne(&vec); + struct Vec2 vecOne = vec; + } + struct Vec2 vecZeroOrOne = vec; + vec.x = 13; + vec.y = 42; + struct Vec2 vecThirteenAndFourtyTwo = vec; + return 0; +} diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc new file mode 100644 index 00000000000..8dc1d684e3a --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc @@ -0,0 +1,11 @@ +CORE +main.c +--variable-sensitivity --interval-values --structs --pointers --show +^EXIT=0$ +^SIGNAL=0$ +main::1::vecMinusTenAndTen \(\) -> {.x=\[11111111111111111111111111110110, 11111111111111111111111111110110\] \@ \[\d*\], .y=\[00000000000000000000000000001010, 00000000000000000000000000001010\] \@ \[\d*\]} +main::1::1::vecZero \(\) -> {.x=\[00000000000000000000000000000000, 00000000000000000000000000000000\] \@ \[\d*\], .y=\[00000000000000000000000000000000, 00000000000000000000000000000000\] \@ \[\d*\]} \@ \[\d*] +main::1::2::vecOne \(\) -> {.x=\[00000000000000000000000000000001, 00000000000000000000000000000001\] \@ \[\d*\], .y=\[00000000000000000000000000000001, 00000000000000000000000000000001\] \@ \[\d*\]} \@ \[\d*\] +main::1::vecZeroOrOne \(\) -> {.x=\[00000000000000000000000000000000, 00000000000000000000000000000001\] \@ \[\d*\], .y=\[00000000000000000000000000000000, 00000000000000000000000000000001\] \@ \[\d*\]} \@ \[\d*\] +main::1::vecThirteenAndFourtyTwo \(\) -> {.x=\[00000000000000000000000000001101, 00000000000000000000000000001101\] \@ \[\d*\], .y=\[00000000000000000000000000101010, 00000000000000000000000000101010\] \@ \[\d*\]} \@ \[\d*\] +-- diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-float/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-float/main.c new file mode 100644 index 00000000000..78b6e53b0c2 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-float/main.c @@ -0,0 +1,19 @@ +#include + +int main(void) +{ + float x = 0.0f; + float zero = x; + int nondet_condition; + if(nondet_condition) { + x = 1.0f; + float one = x; + } else { + x = -1.0f; + float minus_one = x; + } + float between_minus_one_and_one = x; + x = 13.0f; + float thirteen = x; + return 0; +} diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-float/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-float/test.desc new file mode 100644 index 00000000000..7dd2b52d752 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-float/test.desc @@ -0,0 +1,11 @@ +CORE +main.c +--variable-sensitivity --interval-values --show +main::1::zero \(\) -> \[00000000000000000000000000000000, 00000000000000000000000000000000\] +main::1::1::one \(\) -> \[00111111100000000000000000000000, 00111111100000000000000000000000\] +main::1::2::minus_one \(\) -> \[10111111100000000000000000000000, 10111111100000000000000000000000\] +main::1::between_minus_one_and_one \(\) -> \[10111111100000000000000000000000, 00111111100000000000000000000000\] +main::1::thirteen \(\) -> \[01000001010100000000000000000000, 01000001010100000000000000000000\] +^EXIT=0$ +^SIGNAL=0$ +-- \ No newline at end of file diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values/main.c new file mode 100644 index 00000000000..be6bfc9dfd8 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values/main.c @@ -0,0 +1,19 @@ +#include + +int main(void) +{ + int x = 0; + int zero = x; + int nondet_condition; + if(nondet_condition) { + x = 1; + int one = x; + } else { + x = -1; + int minus_one = x; + } + int between_minus_one_and_one = x; + x = 13; + int thirteen = x; + return 0; +} diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values/test.desc new file mode 100644 index 00000000000..dd538280683 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values/test.desc @@ -0,0 +1,11 @@ +CORE +main.c +--variable-sensitivity --interval-values --show +^EXIT=0$ +^SIGNAL=0$ +main::1::zero \(\) -> \[00000000000000000000000000000000, 00000000000000000000000000000000\] +main::1::1::one \(\) -> \[00000000000000000000000000000001, 00000000000000000000000000000001\] +main::1::2::minus_one \(\) -> \[11111111111111111111111111111111, 11111111111111111111111111111111\] +main::1::between_minus_one_and_one \(\) -> \[11111111111111111111111111111111, 00000000000000000000000000000001\] +main::1::thirteen \(\) -> \[00000000000000000000000000001101, 00000000000000000000000000001101\] +-- \ No newline at end of file From 2b05e2ba631b6cb8ed3d2f8caa9ce725a3efc066 Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 11:27:04 +0000 Subject: [PATCH 219/342] Various code style fixes in intervals code --- .../interval_abstract_value.cpp | 59 ++++--------------- .../interval_abstract_value.h | 7 +-- 2 files changed, 14 insertions(+), 52 deletions(-) diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index c3aed5a5efd..24fd24fa09b 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -1,8 +1,8 @@ /*******************************************************************\ - Module: analyses variable-sensitivity + Module: analyses variable-sensitivity intervals - Author: Thomas Kiley, thomas.kiley@diffblue.com + Author: Diffblue Ltd. \*******************************************************************/ @@ -92,21 +92,6 @@ void interval_abstract_valuet::output( } } -/*******************************************************************\ - -Function: interval_abstract_valuet::merge - - Inputs: - other - the abstract object to merge with - - Outputs: Returns the result of the merge - - Purpose: Attempts to do a interval/interval merge if both are intervals, - otherwise falls back to the parent merge - - -\*******************************************************************/ - abstract_object_pointert interval_abstract_valuet::merge( abstract_object_pointert other) const { @@ -114,31 +99,22 @@ abstract_object_pointert interval_abstract_valuet::merge( std::dynamic_pointer_cast(other); if(cast_other) { - return merge_interval_interval(cast_other); + return merge_intervals(cast_other); } else { - // TODO(tkiley): How do we set the result to be toppish? Does it matter? return abstract_valuet::merge(other); } } -/*******************************************************************\ - -Function: interval_abstract_valuet::merge_interval_interval - - Inputs: - other - the abstract object to merge with - - 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 interval abstract value into this one - -\*******************************************************************/ - -abstract_object_pointert interval_abstract_valuet::merge_interval_interval( +/// Merge another interval abstract object with this one +/// \param other The interval abstract object to merge with +/// \return This if the other interval is subsumed by this, +/// other if this is subsumed by other. +/// Otherwise, a new interval abstract object +/// with the smallest interval that subsumes both +/// this and other +abstract_object_pointert interval_abstract_valuet::merge_intervals( interval_abstract_value_pointert other) const { if(is_bottom() || other->interval.contains(interval)) @@ -156,17 +132,4 @@ abstract_object_pointert interval_abstract_valuet::merge_interval_interval( constant_interval_exprt::get_min(interval.get_lower(), other->interval.get_lower()), constant_interval_exprt::get_max(interval.get_upper(), other->interval.get_upper()))); } - -#if 0 - // Can we actually merge these value - if(value==other->value) - { - return shared_from_this(); - } - else - { - return abstract_valuet::merge(other); - } - } -#endif } diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h index 60857c2ab95..0d580d2a914 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.h +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -1,8 +1,8 @@ /*******************************************************************\ - Module: analyses variable-sensitivity + Module: analyses variable-sensitivity intervals - Author: Thomas Kiley, thomas.kiley@diffblue.com + Author: Diffblue Ltd. \*******************************************************************/ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_INTERVAL_ABSTRACT_VALUE_H @@ -64,11 +64,10 @@ class interval_abstract_valuet:public abstract_valuet abstract_object_pointert other) const override; private : - abstract_object_pointert merge_interval_interval( + abstract_object_pointert merge_intervals( interval_abstract_value_pointert other) const; constant_interval_exprt interval; - //exprt value; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_INTERVAL_ABSTRACT_VALUE_H From 0f3d70f69005f95c96f8dcdf40a1bb24f2a5e6ed Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Tue, 22 May 2018 16:45:07 +0100 Subject: [PATCH 220/342] Move interval value constructors to .cpp --- .../interval_abstract_value.cpp | 28 +++++++++++++++++-- .../interval_abstract_value.h | 20 ++++--------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index 24fd24fa09b..f3fd1e38e70 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -15,12 +15,31 @@ #include "interval_abstract_value.h" +static inline exprt look_through_casts(exprt e) { + while(e.id() == ID_typecast) { + e = e.op0(); + } + return e; +} + +static inline constant_interval_exprt make_interval_expr(exprt e) { + e = look_through_casts(e); + if(e.id() == ID_constant_interval) { + return to_constant_interval_expr(e); + } else if(e.id() == ID_constant) { + return constant_interval_exprt(e, e); + } else { + // not directly representable, so just return TOP + return constant_interval_exprt(e.type()); + } +} + interval_abstract_valuet::interval_abstract_valuet(typet t): - abstract_valuet(t), interval() + abstract_valuet(t), interval(t) {} interval_abstract_valuet::interval_abstract_valuet(typet t, bool tp, bool bttm): - abstract_valuet(t, tp, bttm), interval() + abstract_valuet(t, tp, bttm), interval(t) {} interval_abstract_valuet::interval_abstract_valuet( @@ -133,3 +152,8 @@ abstract_object_pointert interval_abstract_valuet::merge_intervals( constant_interval_exprt::get_max(interval.get_upper(), other->interval.get_upper()))); } } + +interval_abstract_valuet::interval_abstract_valuet(const exprt e, const abstract_environmentt &environment, + const namespacet &ns) + : interval_abstract_valuet(make_interval_expr(e)) +{} diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h index 0d580d2a914..085e60d4b69 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.h +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -20,38 +20,28 @@ class interval_abstract_valuet:public abstract_valuet private: typedef sharing_ptrt interval_abstract_value_pointert; - static inline constant_interval_exprt make_interval_expr(exprt e) { - if(e.id() == ID_constant_interval) { - return to_constant_interval_expr(e); - } else { - return constant_interval_exprt(e, e); - } - } + public: explicit interval_abstract_valuet(typet t); interval_abstract_valuet(typet t, bool tp, bool bttm); + interval_abstract_valuet( const constant_interval_exprt e); + interval_abstract_valuet( const exprt e, const abstract_environmentt &environment, - const namespacet &ns) - : interval_abstract_valuet(make_interval_expr(e)) - { - - } + const namespacet &ns); - virtual ~interval_abstract_valuet() {} + ~interval_abstract_valuet() override = default; virtual exprt to_constant() const override; -#if 1 // Interface for transforms abstract_object_pointert expression_transform( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns) const override; -#endif virtual void output( std::ostream &out, From c6d83273a3d858ac0668d333496993546e19e40e Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Thu, 24 May 2018 11:35:46 +0100 Subject: [PATCH 221/342] Fix interval abstract value constructor Set interval abstract value to top or bottom if the contained interval is top or bottom. --- src/analyses/variable-sensitivity/interval_abstract_value.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index f3fd1e38e70..c113f869831 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -44,7 +44,7 @@ interval_abstract_valuet::interval_abstract_valuet(typet t, bool tp, bool bttm): interval_abstract_valuet::interval_abstract_valuet( const constant_interval_exprt e): - abstract_valuet(e.type(), false, false), interval(e) + abstract_valuet(e.type(), e.is_top(), e.is_bottom()), interval(e) { } From 41b5d226b65cd33cfe9d5571f0dba0402212fa2d Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Thu, 24 May 2018 12:17:36 +0100 Subject: [PATCH 222/342] Fix infinite loop in interval values Make sure that the same value can't be merged more than ten times. This is because in loops intervals kept changing so we never reached a fixed point. --- .../interval_abstract_value.cpp | 20 +++++++++++++++---- .../interval_abstract_value.h | 4 ++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index c113f869831..d26c0481fcb 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -43,8 +43,8 @@ interval_abstract_valuet::interval_abstract_valuet(typet t, bool tp, bool bttm): {} interval_abstract_valuet::interval_abstract_valuet( - const constant_interval_exprt e): - abstract_valuet(e.type(), e.is_top(), e.is_bottom()), interval(e) + const constant_interval_exprt e) + : interval_abstract_valuet(e, 0) { } @@ -148,8 +148,11 @@ abstract_object_pointert interval_abstract_valuet::merge_intervals( { return std::make_shared( constant_interval_exprt( - constant_interval_exprt::get_min(interval.get_lower(), other->interval.get_lower()), - constant_interval_exprt::get_max(interval.get_upper(), other->interval.get_upper()))); + constant_interval_exprt::get_min( + interval.get_lower(), other->interval.get_lower()), + constant_interval_exprt::get_max( + interval.get_upper(), other->interval.get_upper())), + std::max(merge_count, other->merge_count) + 1); } } @@ -157,3 +160,12 @@ interval_abstract_valuet::interval_abstract_valuet(const exprt e, const abstract const namespacet &ns) : interval_abstract_valuet(make_interval_expr(e)) {} + +interval_abstract_valuet::interval_abstract_valuet( + constant_interval_exprt e, + int merge_count) + : abstract_valuet(e.type(), e.is_top() || merge_count > 10, e.is_bottom()), + interval(e), + merge_count(merge_count) +{ +} diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h index 085e60d4b69..c5acc621d73 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.h +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -25,6 +25,8 @@ class interval_abstract_valuet:public abstract_valuet explicit interval_abstract_valuet(typet t); interval_abstract_valuet(typet t, bool tp, bool bttm); + explicit interval_abstract_valuet(constant_interval_exprt e, int merge_count); + interval_abstract_valuet( const constant_interval_exprt e); @@ -58,6 +60,8 @@ private : interval_abstract_value_pointert other) const; constant_interval_exprt interval; + + int merge_count; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_INTERVAL_ABSTRACT_VALUE_H From 75de2073fc4bb7c35854b1c643d9836a73f4f66f Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Thu, 24 May 2018 18:16:15 +0100 Subject: [PATCH 223/342] Moved rounding mode aware arithmetic to constant abstract value --- .../variable-sensitivity/abstract_object.cpp | 95 +++------------ .../variable-sensitivity/abstract_object.h | 5 - .../constant_abstract_value.cpp | 108 ++++++++++++++++++ .../constant_abstract_value.h | 10 ++ 4 files changed, 131 insertions(+), 87 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 8877ef815be..208b8f82c85 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -186,98 +186,29 @@ abstract_object_pointert abstract_objectt::expression_transform( const abstract_environmentt &environment, const namespacet &ns) const { - // try finding the rounding mode. If it's not constant, try - // seeing if we can get the same result with all rounding modes - auto rounding_mode_symbol = - symbol_exprt("__CPROVER_rounding_mode", signedbv_typet(32)); - auto rounding_mode_value = environment.eval(rounding_mode_symbol, ns); - auto rounding_mode_constant = rounding_mode_value->to_constant(); - if(rounding_mode_constant.is_nil()) + exprt copy = expr; + + for (exprt &op : copy.operands()) { - return try_transform_expr_with_all_rounding_modes(expr, environment, ns); + abstract_object_pointert op_abstract_object = environment.eval(op, ns); + const exprt &const_op = op_abstract_object->to_constant(); + op = const_op.is_nil() ? op : const_op; } - exprt adjusted_expr = expr; - adjust_float_expressions(adjusted_expr, ns); - exprt constant_replaced_expr = adjusted_expr; - constant_replaced_expr.operands().clear(); + simplify(copy, ns); - // Two passes over the expression - one for simplification, - // another to check if there are any top subexpressions left - for(const exprt &op : adjusted_expr.operands()) + for (const exprt &op : copy.operands()) { - abstract_object_pointert lhs_abstract_object=environment.eval(op, ns); - const exprt &lhs_value=lhs_abstract_object->to_constant(); - if(lhs_value.is_nil()) - { - // do not give up if a sub-expression is not a constant, - // because the whole expression may still be simplified in some cases - constant_replaced_expr.operands().push_back(op); - } - else - { - // 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); + abstract_object_pointert op_abstract_object = environment.eval(op, ns); + const exprt &const_op = op_abstract_object->to_constant(); - for(const exprt &op : simplified.operands()) - { - abstract_object_pointert lhs_abstract_object = environment.eval(op, ns); - const exprt &lhs_value = lhs_abstract_object->to_constant(); - if(lhs_value.is_nil()) + if(const_op.is_nil()) { - return environment.abstract_object_factory( - simplified.type(), ns, true, false); + return environment.abstract_object_factory(copy.type(), ns, true); } } - return environment.abstract_object_factory(simplified.type(), simplified, ns); -} - -abstract_object_pointert -abstract_objectt::try_transform_expr_with_all_rounding_modes( - const exprt &expr, - const abstract_environmentt &environment, - const namespacet &ns) const -{ - const symbol_exprt rounding_mode_symbol = - symbol_exprt("__CPROVER_rounding_mode", signedbv_typet(32)); - // NOLINTNEXTLINE (whitespace/braces) - auto rounding_modes = std::array{ - // NOLINTNEXTLINE (whitespace/braces) - {ieee_floatt::ROUND_TO_EVEN, - ieee_floatt::ROUND_TO_ZERO, - ieee_floatt::ROUND_TO_MINUS_INF, - // NOLINTNEXTLINE (whitespace/braces) - ieee_floatt::ROUND_TO_PLUS_INF}}; - std::vector possible_results; - for(auto current_rounding_mode : rounding_modes) - { - abstract_environmentt child_env(environment); - child_env.assign( - rounding_mode_symbol, - child_env.abstract_object_factory( - signedbv_typet(32), - from_integer( - mp_integer(static_cast(current_rounding_mode)), - signedbv_typet(32)), - ns), - ns); - possible_results.push_back(expression_transform(expr, child_env, ns)); - } - auto first = possible_results.front()->to_constant(); - for(auto const &possible_result : possible_results) - { - auto current = possible_result->to_constant(); - if(current.is_nil() || current != first) - { - return environment.abstract_object_factory(expr.type(), ns); - } - } - return possible_results.front(); + return environment.abstract_object_factory(copy.type(), copy, ns); } /** diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 6bf9d5c8b5b..688fd94d6d2 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -255,11 +255,6 @@ 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; this->make_top_internal(); } void clear_top() { top=false; this->clear_top_internal(); } - - abstract_object_pointert try_transform_expr_with_all_rounding_modes( - const exprt &expr, - const abstract_environmentt &environment, - const namespacet &ns) const; }; template diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index 53ce145f3cd..15e8752ce78 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -8,8 +8,17 @@ #include +#include +#include #include +#include +#include +#include +#include +#include + +#include "abstract_enviroment.h" #include "constant_abstract_value.h" constant_abstract_valuet::constant_abstract_valuet(typet t): @@ -27,6 +36,105 @@ constant_abstract_valuet::constant_abstract_valuet( abstract_valuet(e.type(), false, false), value(e) {} +abstract_object_pointert constant_abstract_valuet::expression_transform( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const +{ + // try finding the rounding mode. If it's not constant, try + // seeing if we can get the same result with all rounding modes + auto rounding_mode_symbol = + symbol_exprt("__CPROVER_rounding_mode", signedbv_typet(32)); + auto rounding_mode_value = environment.eval(rounding_mode_symbol, ns); + auto rounding_mode_constant = rounding_mode_value->to_constant(); + if(rounding_mode_constant.is_nil()) + { + return try_transform_expr_with_all_rounding_modes(expr, environment, ns); + } + + exprt adjusted_expr = expr; + adjust_float_expressions(adjusted_expr, ns); + exprt constant_replaced_expr = adjusted_expr; + constant_replaced_expr.operands().clear(); + + // Two passes over the expression - one for simplification, + // another to check if there are any top subexpressions left + for(const exprt &op : adjusted_expr.operands()) + { + abstract_object_pointert lhs_abstract_object=environment.eval(op, ns); + const exprt &lhs_value=lhs_abstract_object->to_constant(); + if(lhs_value.is_nil()) + { + // do not give up if a sub-expression is not a constant, + // because the whole expression may still be simplified in some cases + constant_replaced_expr.operands().push_back(op); + } + else + { + // 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); + + for(const exprt &op : simplified.operands()) + { + abstract_object_pointert lhs_abstract_object = environment.eval(op, ns); + const exprt &lhs_value = lhs_abstract_object->to_constant(); + if(lhs_value.is_nil()) + { + return environment.abstract_object_factory( + simplified.type(), ns, true, false); + } + } + + return environment.abstract_object_factory(simplified.type(), simplified, ns); +} + +abstract_object_pointert +constant_abstract_valuet::try_transform_expr_with_all_rounding_modes( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const +{ + const symbol_exprt rounding_mode_symbol = + symbol_exprt("__CPROVER_rounding_mode", signedbv_typet(32)); + // NOLINTNEXTLINE (whitespace/braces) + auto rounding_modes = std::array{ + // NOLINTNEXTLINE (whitespace/braces) + {ieee_floatt::ROUND_TO_EVEN, + ieee_floatt::ROUND_TO_ZERO, + ieee_floatt::ROUND_TO_MINUS_INF, + // NOLINTNEXTLINE (whitespace/braces) + ieee_floatt::ROUND_TO_PLUS_INF}}; + std::vector possible_results; + for(auto current_rounding_mode : rounding_modes) + { + abstract_environmentt child_env(environment); + child_env.assign( + rounding_mode_symbol, + child_env.abstract_object_factory( + signedbv_typet(32), + from_integer( + mp_integer(static_cast(current_rounding_mode)), + signedbv_typet(32)), + ns), + ns); + possible_results.push_back(expression_transform(expr, child_env, ns)); + } + auto first = possible_results.front()->to_constant(); + for(auto const &possible_result : possible_results) + { + auto current = possible_result->to_constant(); + if(current.is_nil() || current != first) + { + return environment.abstract_object_factory(expr.type(), ns); + } + } + return possible_results.front(); +} + exprt constant_abstract_valuet::to_constant() 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 752b48734b4..78ab2a004cd 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -29,6 +29,11 @@ class constant_abstract_valuet:public abstract_valuet virtual ~constant_abstract_valuet() {} + virtual abstract_object_pointert expression_transform( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const; + virtual exprt to_constant() const override; virtual void output( @@ -41,6 +46,11 @@ class constant_abstract_valuet:public abstract_valuet virtual abstract_object_pointert merge( abstract_object_pointert other) const override; + abstract_object_pointert try_transform_expr_with_all_rounding_modes( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) const; + private : abstract_object_pointert merge_constant_constant( constant_abstract_value_pointert other) const; From e0ec69718bf49aa5f167dbdeb296b743545ed42d Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Thu, 24 May 2018 18:20:29 +0100 Subject: [PATCH 224/342] Calling eval_expression on top abstract object --- .../variable-sensitivity/abstract_enviroment.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 667630067c2..b5cf5dff2ce 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -651,9 +651,13 @@ bool abstract_environmentt::verify() const 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 eval_obj=abstract_object_factory(e.type(), e, ns); + // We create a temporary top abstract object (according to the + // type of the expression), and call expression transform on it. + // The value of the temporary abstract object is ignored, its + // purpose is just to dispatch the expression transform call to + // a concrete subtype of abstract_objectt. + abstract_object_pointert eval_obj=abstract_object_factory( + e.type(), ns, true); return eval_obj->expression_transform(e, *this, ns); } From 6dfa1854298854db7f37abad47fb6d295df92f74 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Fri, 25 May 2018 17:12:23 +0100 Subject: [PATCH 225/342] Escape curly braces in variable sensitivity float regression test --- .../test.desc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc index 8dc1d684e3a..c619d4f2182 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc @@ -3,9 +3,9 @@ main.c --variable-sensitivity --interval-values --structs --pointers --show ^EXIT=0$ ^SIGNAL=0$ -main::1::vecMinusTenAndTen \(\) -> {.x=\[11111111111111111111111111110110, 11111111111111111111111111110110\] \@ \[\d*\], .y=\[00000000000000000000000000001010, 00000000000000000000000000001010\] \@ \[\d*\]} -main::1::1::vecZero \(\) -> {.x=\[00000000000000000000000000000000, 00000000000000000000000000000000\] \@ \[\d*\], .y=\[00000000000000000000000000000000, 00000000000000000000000000000000\] \@ \[\d*\]} \@ \[\d*] -main::1::2::vecOne \(\) -> {.x=\[00000000000000000000000000000001, 00000000000000000000000000000001\] \@ \[\d*\], .y=\[00000000000000000000000000000001, 00000000000000000000000000000001\] \@ \[\d*\]} \@ \[\d*\] -main::1::vecZeroOrOne \(\) -> {.x=\[00000000000000000000000000000000, 00000000000000000000000000000001\] \@ \[\d*\], .y=\[00000000000000000000000000000000, 00000000000000000000000000000001\] \@ \[\d*\]} \@ \[\d*\] -main::1::vecThirteenAndFourtyTwo \(\) -> {.x=\[00000000000000000000000000001101, 00000000000000000000000000001101\] \@ \[\d*\], .y=\[00000000000000000000000000101010, 00000000000000000000000000101010\] \@ \[\d*\]} \@ \[\d*\] +main::1::vecMinusTenAndTen \(\) -> \{.x=\[11111111111111111111111111110110, 11111111111111111111111111110110\] \@ \[\d*\], .y=\[00000000000000000000000000001010, 00000000000000000000000000001010\] \@ \[\d*\]\} +main::1::1::vecZero \(\) -> \{.x=\[00000000000000000000000000000000, 00000000000000000000000000000000\] \@ \[\d*\], .y=\[00000000000000000000000000000000, 00000000000000000000000000000000\] \@ \[\d*\]\} \@ \[\d*] +main::1::2::vecOne \(\) -> \{.x=\[00000000000000000000000000000001, 00000000000000000000000000000001\] \@ \[\d*\], .y=\[00000000000000000000000000000001, 00000000000000000000000000000001\] \@ \[\d*\]\} \@ \[\d*\] +main::1::vecZeroOrOne \(\) -> \{.x=\[00000000000000000000000000000000, 00000000000000000000000000000001\] \@ \[\d*\], .y=\[00000000000000000000000000000000, 00000000000000000000000000000001\] \@ \[\d*\]\} \@ \[\d*\] +main::1::vecThirteenAndFourtyTwo \(\) -> \{.x=\[00000000000000000000000000001101, 00000000000000000000000000001101\] \@ \[\d*\], .y=\[00000000000000000000000000101010, 00000000000000000000000000101010\] \@ \[\d*\]\} \@ \[\d*\] -- From 391b0a69351c98614fa3b5dfa62e6c74065d0065 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Fri, 25 May 2018 17:16:24 +0100 Subject: [PATCH 226/342] Add struct case to abstract environment eval --- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index b5cf5dff2ce..2353b55908d 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -100,6 +100,10 @@ abstract_object_pointert abstract_environmentt::eval( { return abstract_object_factory(simplified_expr.type(), simplified_expr, ns); } + else if(simplified_id==ID_struct) + { + return abstract_object_factory(simplified_expr.type(), simplified_expr, ns); + } else if(simplified_id==ID_constant) { return abstract_object_factory( From 3674800fd64c60597bc5d82b8cde3c29fa4e436a Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Fri, 25 May 2018 17:24:45 +0100 Subject: [PATCH 227/342] Basic interval arithmetic --- .../abstract_enviroment.cpp | 10 +- .../variable-sensitivity/abstract_object.cpp | 1 + .../variable-sensitivity/abstract_object.h | 1 + .../constant_abstract_value.cpp | 7 +- .../constant_abstract_value.h | 1 + .../context_abstract_object.cpp | 19 ++- .../context_abstract_object.h | 1 + .../interval_abstract_value.cpp | 110 ++++++++++++++++-- .../interval_abstract_value.h | 1 + 9 files changed, 141 insertions(+), 10 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 2353b55908d..38e091dc4e0 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -662,7 +662,15 @@ abstract_object_pointert abstract_environmentt::eval_expression( // a concrete subtype of abstract_objectt. abstract_object_pointert eval_obj=abstract_object_factory( e.type(), ns, true); - return eval_obj->expression_transform(e, *this, ns); + + std::vector operands; + + for(const auto &op : e.operands()) + { + operands.push_back(eval(op, ns)); + } + + return eval_obj->expression_transform(e, operands, *this, ns); } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 208b8f82c85..acd37f8ff97 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -183,6 +183,7 @@ Function: abstract_objectt::expression_transform abstract_object_pointert abstract_objectt::expression_transform( const exprt &expr, + const std::vector &operands, const abstract_environmentt &environment, const namespacet &ns) const { diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 688fd94d6d2..03a571bd742 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -95,6 +95,7 @@ class abstract_objectt:public std::enable_shared_from_this // Interface for transforms virtual abstract_object_pointert expression_transform( const exprt &expr, + const std::vector &operands, const abstract_environmentt &environment, const namespacet &ns) const; diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index 15e8752ce78..41986540d57 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -38,6 +38,7 @@ constant_abstract_valuet::constant_abstract_valuet( abstract_object_pointert constant_abstract_valuet::expression_transform( const exprt &expr, + const std::vector &operands, const abstract_environmentt &environment, const namespacet &ns) const { @@ -121,7 +122,11 @@ constant_abstract_valuet::try_transform_expr_with_all_rounding_modes( signedbv_typet(32)), ns), ns); - possible_results.push_back(expression_transform(expr, child_env, ns)); + + // Dummy vector as the called expression_transform() ignores it + std::vector dummy; + possible_results.push_back( + expression_transform(expr, dummy, child_env, ns)); } auto first = possible_results.front()->to_constant(); for(auto const &possible_result : possible_results) diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 78ab2a004cd..45479f02deb 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -31,6 +31,7 @@ class constant_abstract_valuet:public abstract_valuet virtual abstract_object_pointert expression_transform( const exprt &expr, + const std::vector &operands, const abstract_environmentt &environment, const namespacet &ns) const; diff --git a/src/analyses/variable-sensitivity/context_abstract_object.cpp b/src/analyses/variable-sensitivity/context_abstract_object.cpp index 7f4a3592533..796c4e74ef9 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/context_abstract_object.cpp @@ -105,10 +105,27 @@ abstract_object_pointert context_abstract_objectt::write( */ abstract_object_pointert context_abstract_objectt::expression_transform( const exprt &expr, + const std::vector &operands, const abstract_environmentt &environment, const namespacet &ns) const { - return child_abstract_object->expression_transform(expr, environment, ns); + PRECONDITION(expr.operands().size() == operands.size()); + + std::vector child_operands; + + std::transform( + operands.begin(), + operands.end(), + std::back_inserter(child_operands), + [](const abstract_object_pointert &op) { + PRECONDITION(op != nullptr); + auto p = std::dynamic_pointer_cast(op); + INVARIANT(p, "Operand shall be of type context_abstract_objectt"); + return p->child_abstract_object; + }); + + return child_abstract_object->expression_transform( + expr, child_operands, environment, ns); } /** diff --git a/src/analyses/variable-sensitivity/context_abstract_object.h b/src/analyses/variable-sensitivity/context_abstract_object.h index 734dda7d569..80487386878 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.h +++ b/src/analyses/variable-sensitivity/context_abstract_object.h @@ -74,6 +74,7 @@ class context_abstract_objectt: public abstract_objectt abstract_object_pointert expression_transform( const exprt &expr, + const std::vector &operands, const abstract_environmentt &environment, const namespacet &ns) const; diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index d26c0481fcb..8727a7d9fa3 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -51,6 +51,9 @@ interval_abstract_valuet::interval_abstract_valuet( exprt interval_abstract_valuet::to_constant() const { + return abstract_objectt::to_constant(); + +#if 0 if(!is_top() && !is_bottom()) { return this->interval; @@ -59,26 +62,119 @@ exprt interval_abstract_valuet::to_constant() const { return abstract_objectt::to_constant(); } +#endif } -#if 1 -// Interface for transforms abstract_object_pointert interval_abstract_valuet::expression_transform( const exprt &expr, + const std::vector &operands, const abstract_environmentt &environment, const namespacet &ns) const { - if(expr.id() == ID_constant_interval) + std::size_t num_operands = expr.operands().size(); + PRECONDITION(operands.size() == num_operands); + + const typet &type = expr.type(); + + if(num_operands == 0) + return environment.abstract_object_factory(type, ns, true); + + if(expr.id() == ID_plus) { - return environment.abstract_object_factory(expr.type(), expr, ns); + constant_exprt zero = constant_interval_exprt::zero(type); + constant_interval_exprt interval(zero); + INVARIANT(interval.is_zero(), "Starting interval must be zero"); + + for(const auto &op : operands) + { + const auto iav + = std::dynamic_pointer_cast(op); + INVARIANT(iav, ""); + + const constant_interval_exprt &interval_next = iav->interval; + interval = interval.plus(interval_next); + } + + INVARIANT(interval.type() == type, ""); + + return environment.abstract_object_factory(type, interval, ns); } - else + else if(num_operands == 1) { - return abstract_objectt::expression_transform(expr, environment, ns); + const auto iav = + std::dynamic_pointer_cast(operands[0]); + + INVARIANT(iav, ""); + + const constant_interval_exprt &interval = iav->interval; + + // The typecast case should probably be handled by constant_interval_exprt + // directly as well + if(expr.id() == ID_typecast) + { + const typecast_exprt &tce = to_typecast_expr(expr); + + exprt lower = interval.get_lower(); + lower.type() = tce.type(); + + exprt upper = interval.get_upper(); + upper.type() = tce.type(); + + const constant_interval_exprt new_interval(lower, upper, tce.type()); + return environment.abstract_object_factory(tce.type(), new_interval, ns); + } + else + { + const constant_interval_exprt &interval_result = interval.eval(expr.id()); + INVARIANT(interval_result.type() == type, ""); + return environment.abstract_object_factory(type, interval_result, ns); + } } -} + else if(num_operands == 2) + { + const auto iav0 + = std::dynamic_pointer_cast(operands[0]); + + INVARIANT(iav0, ""); + + const auto iav1 + = std::dynamic_pointer_cast(operands[1]); + + INVARIANT(iav1, ""); + + const constant_interval_exprt &interval0 = iav0->interval; + const constant_interval_exprt &interval1 = iav1->interval; + + // constant_interval_exprt currently does not correctly handle the type of + // relational operators (it assigns to it the type of the first operand + // as opposed to ID_bool) +#if 0 + constant_interval_exprt interval + = interval0.eval(expr.id(), interval1); + + interval.type() = type; + + return environment.abstract_object_factory(type, interval, ns); #endif +#if 1 + if(expr.id() == ID_equal) + { + + INVARIANT(type.id() == ID_bool, ""); + + tvt tv = interval0.equal(interval1); + + constant_interval_exprt ie(type); + const constant_interval_exprt &interval = ie.tv_to_interval(tv); + return environment.abstract_object_factory(type, interval, ns); +#endif + } + } + + return environment.abstract_object_factory(type, ns, true); +} + void interval_abstract_valuet::output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const { diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h index c5acc621d73..ad09be67c22 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.h +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -42,6 +42,7 @@ class interval_abstract_valuet:public abstract_valuet // Interface for transforms abstract_object_pointert expression_transform( const exprt &expr, + const std::vector &operands, const abstract_environmentt &environment, const namespacet &ns) const override; From b60ba4341c50a720f7ab1617468b1e37b6582d80 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Tue, 29 May 2018 13:18:29 +0100 Subject: [PATCH 228/342] Interval arithmetic regression tests --- .../main.c | 14 +++++++++++++ .../test.desc | 7 +++++++ .../main.c | 20 +++++++++++++++++++ .../test.desc | 7 +++++++ .../main.c | 16 +++++++++++++++ .../test.desc | 7 +++++++ 6 files changed, 71 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/test.desc create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/test.desc create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/main.c new file mode 100644 index 00000000000..37c9c1b362f --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/main.c @@ -0,0 +1,14 @@ + +int main(void) +{ + int x; + int y; + int z; + + x = 1; + y = 2; + + z = x + y; + + return 0; +} diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/test.desc new file mode 100644 index 00000000000..4bbbcd58c41 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/test.desc @@ -0,0 +1,7 @@ +CORE +main.c +--variable-sensitivity --interval-values --show +^EXIT=0$ +^SIGNAL=0$ +main::1::z \(\) -> \[00000000000000000000000000000011, 00000000000000000000000000000011\] +-- diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/main.c new file mode 100644 index 00000000000..c379294b826 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/main.c @@ -0,0 +1,20 @@ + +int main(void) +{ + int x; + int y; + int z; + int nondet; + + x = 1; + y = 2; + + if(nondet) + { + y = 3; + } + + z = x + y; + + return 0; +} diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/test.desc new file mode 100644 index 00000000000..e6da64be919 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/test.desc @@ -0,0 +1,7 @@ +CORE +main.c +--variable-sensitivity --interval-values --show +^EXIT=0$ +^SIGNAL=0$ +main::1::z \(\) -> \[00000000000000000000000000000011, 00000000000000000000000000000100\] +-- diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/main.c new file mode 100644 index 00000000000..28d6464e1a3 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/main.c @@ -0,0 +1,16 @@ + +int main(void) +{ + int x; + int y; + int z; + int a; + + x = 1; + y = 2; + z = 3; + + a = x + y + z; + + return 0; +} diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/test.desc new file mode 100644 index 00000000000..0d93a20e4a3 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/test.desc @@ -0,0 +1,7 @@ +CORE +main.c +--variable-sensitivity --interval-values --show +^EXIT=0$ +^SIGNAL=0$ +main::1::a \(\) -> \[00000000000000000000000000000110, 00000000000000000000000000000110\] +-- From 2951a1757af8a2c0ac9ce50c29493e759b074282 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Tue, 29 May 2018 17:10:25 +0100 Subject: [PATCH 229/342] use eval to evaluate binary operators in interval abstract object --- .../interval_abstract_value.cpp | 27 +++---------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index 8727a7d9fa3..698792ee01a 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -145,31 +145,12 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( const constant_interval_exprt &interval0 = iav0->interval; const constant_interval_exprt &interval1 = iav1->interval; - // constant_interval_exprt currently does not correctly handle the type of - // relational operators (it assigns to it the type of the first operand - // as opposed to ID_bool) -#if 0 - constant_interval_exprt interval - = interval0.eval(expr.id(), interval1); - - interval.type() = type; - - return environment.abstract_object_factory(type, interval, ns); -#endif - -#if 1 - if(expr.id() == ID_equal) - { + constant_interval_exprt interval + = interval0.eval(expr.id(), interval1); - INVARIANT(type.id() == ID_bool, ""); - - tvt tv = interval0.equal(interval1); + INVARIANT(interval.type() == type, ""); - constant_interval_exprt ie(type); - const constant_interval_exprt &interval = ie.tv_to_interval(tv); - return environment.abstract_object_factory(type, interval, ns); -#endif - } + return environment.abstract_object_factory(type, interval, ns); } return environment.abstract_object_factory(type, ns, true); From 422741cf9601f2700ba74bdc2c92bdbe7eefbfae Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 11:29:23 +0000 Subject: [PATCH 230/342] Handle typecasts in constant_interval_exprt --- .../variable-sensitivity/interval_abstract_value.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index 698792ee01a..793e446f9b6 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -108,19 +108,15 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( const constant_interval_exprt &interval = iav->interval; - // The typecast case should probably be handled by constant_interval_exprt - // directly as well if(expr.id() == ID_typecast) { const typecast_exprt &tce = to_typecast_expr(expr); - exprt lower = interval.get_lower(); - lower.type() = tce.type(); + const constant_interval_exprt &new_interval + = interval.typecast(tce.type()); - exprt upper = interval.get_upper(); - upper.type() = tce.type(); + INVARIANT(new_interval.type() == type, ""); - const constant_interval_exprt new_interval(lower, upper, tce.type()); return environment.abstract_object_factory(tce.type(), new_interval, ns); } else From 4193f504356e2091c7d436c87f1267214f0220b1 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Tue, 29 May 2018 18:10:06 +0100 Subject: [PATCH 231/342] Typecast from ID_bool to integer types --- .../main.c | 12 ++++++++++++ .../test.desc | 8 ++++++++ 2 files changed, 20 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/main.c new file mode 100644 index 00000000000..c102801ea36 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/main.c @@ -0,0 +1,12 @@ +#include + +int main(void) +{ + bool b1; + bool b2; + + b1 = true; + b2 = !b1; + + return 0; +} diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc new file mode 100644 index 00000000000..4f16401e531 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--variable-sensitivity --interval-values --show +^EXIT=0$ +^SIGNAL=0$ +main::1::b1 \(\) -> \[00000001, 00000001\] +main::1::b2 \(\) -> \[00000000, 00000000\] +-- From b6b550ee5d17f86bfb19413b2c4d1126307fff50 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Wed, 30 May 2018 16:07:09 +0100 Subject: [PATCH 232/342] Addressing review comments --- .../interval_abstract_value.cpp | 50 +++++++++---------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index 793e446f9b6..228a4508cb6 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -74,6 +74,17 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( std::size_t num_operands = expr.operands().size(); PRECONDITION(operands.size() == num_operands); + std::vector> interval_operands; + interval_operands.reserve(num_operands); + + for(const auto &op : operands) + { + const auto iav + = std::dynamic_pointer_cast(op); + INVARIANT(iav, "Should be an interval abstract value"); + interval_operands.push_back(iav); + } + const typet &type = expr.type(); if(num_operands == 0) @@ -85,28 +96,20 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( constant_interval_exprt interval(zero); INVARIANT(interval.is_zero(), "Starting interval must be zero"); - for(const auto &op : operands) + for(const auto &iav : interval_operands) { - const auto iav - = std::dynamic_pointer_cast(op); - INVARIANT(iav, ""); - const constant_interval_exprt &interval_next = iav->interval; interval = interval.plus(interval_next); } - INVARIANT(interval.type() == type, ""); + INVARIANT(interval.type() == type, + "Type of result interval should match expression type"); return environment.abstract_object_factory(type, interval, ns); } else if(num_operands == 1) { - const auto iav = - std::dynamic_pointer_cast(operands[0]); - - INVARIANT(iav, ""); - - const constant_interval_exprt &interval = iav->interval; + const constant_interval_exprt &interval = interval_operands[0]->interval; if(expr.id() == ID_typecast) { @@ -115,36 +118,29 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( const constant_interval_exprt &new_interval = interval.typecast(tce.type()); - INVARIANT(new_interval.type() == type, ""); + INVARIANT(new_interval.type() == type, + "Type of result interval should match expression type"); return environment.abstract_object_factory(tce.type(), new_interval, ns); } else { const constant_interval_exprt &interval_result = interval.eval(expr.id()); - INVARIANT(interval_result.type() == type, ""); + INVARIANT(interval_result.type() == type, + "Type of result interval should match expression type"); return environment.abstract_object_factory(type, interval_result, ns); } } else if(num_operands == 2) { - const auto iav0 - = std::dynamic_pointer_cast(operands[0]); - - INVARIANT(iav0, ""); - - const auto iav1 - = std::dynamic_pointer_cast(operands[1]); - - INVARIANT(iav1, ""); - - const constant_interval_exprt &interval0 = iav0->interval; - const constant_interval_exprt &interval1 = iav1->interval; + const constant_interval_exprt &interval0 = interval_operands[0]->interval; + const constant_interval_exprt &interval1 = interval_operands[1]->interval; constant_interval_exprt interval = interval0.eval(expr.id(), interval1); - INVARIANT(interval.type() == type, ""); + INVARIANT(interval.type() == type, + "Type of result interval should match expression type"); return environment.abstract_object_factory(type, interval, ns); } From 74eb12043fa540a8ca18ebdebd05918a0a324ef7 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Fri, 25 May 2018 17:11:01 +0100 Subject: [PATCH 233/342] Mark failing dependence graph test as FUTURE --- .../variable-sensitivity-dependence-graph/test.desc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc index a10dceacd95..22222bd4c93 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc @@ -1,4 +1,4 @@ -CORE +FUTURE main.c file1.c file2.c --dependence-graph-vs --structs --arrays --show EXIT=0 From e693693b99e2a44f44eaa5560e54c81261341e04 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Tue, 22 May 2018 16:41:32 +0100 Subject: [PATCH 234/342] Make constant_array_abstract_object::eval_index virtual Subclasses may need to override this behaviour --- .../constant_array_abstract_object.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index ad01c74e6f1..f4c4829ae68 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -59,6 +59,12 @@ class constant_array_abstract_objectt:public array_abstract_objectt bool verify() const; + virtual bool eval_index( + const index_exprt &index, + const abstract_environmentt &env, + const namespacet &ns, + mp_integer &out_index) const; + 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 @@ -73,12 +79,6 @@ class constant_array_abstract_objectt:public array_abstract_objectt shared_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; From 1cb1f8112a5916ae8e059c8fc8bb5d462e31aae6 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Tue, 22 May 2018 16:45:07 +0100 Subject: [PATCH 235/342] Move interval value constructors to .cpp --- src/analyses/variable-sensitivity/interval_abstract_value.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h index ad09be67c22..b94514ded86 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.h +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -25,9 +25,9 @@ class interval_abstract_valuet:public abstract_valuet explicit interval_abstract_valuet(typet t); interval_abstract_valuet(typet t, bool tp, bool bttm); - explicit interval_abstract_valuet(constant_interval_exprt e, int merge_count); + interval_abstract_valuet(constant_interval_exprt e, int merge_count); - interval_abstract_valuet( + explicit interval_abstract_valuet( const constant_interval_exprt e); interval_abstract_valuet( From 00af48a41e24bf7b85a8d73ab76ccaddafbf2478 Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 11:53:57 +0000 Subject: [PATCH 236/342] Interval operations --- src/analyses/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/analyses/Makefile b/src/analyses/Makefile index 53bdc61f3c5..fc7a5fdf918 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -52,6 +52,7 @@ SRC = ai.cpp \ variable-sensitivity/write_stack_entry.cpp \ variable-sensitivity/data_dependency_context.cpp \ variable-sensitivity/variable_sensitivity_dependence_graph.cpp \ + variable-sensitivity/interval_abstract_value.cpp \ # Empty last line INCLUDES= -I .. From 45a43764afc8517f62104a97cc67de2bdda664d4 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Tue, 22 May 2018 16:55:17 +0100 Subject: [PATCH 237/342] Add interval arrays to variable sensitivity --- .../main.c | 8 ++ .../test.desc | 5 + .../main.c | 27 +++++ .../test.desc | 7 ++ src/analyses/Makefile | 1 + .../interval_array_abstract_object.cpp | 104 ++++++++++++++++++ .../interval_array_abstract_object.h | 38 +++++++ .../variable_sensitivity_object_factory.cpp | 6 +- 8 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/test.desc create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/test.desc create mode 100644 src/analyses/variable-sensitivity/interval_array_abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/interval_array_abstract_object.h diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/main.c new file mode 100644 index 00000000000..93ec0d18148 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/main.c @@ -0,0 +1,8 @@ +int main(void) +{ + int arr[] = {1,2,3}; + int second_value = arr[1]; + arr[1] = 10; + int second_value_after_write = arr[1]; + return 0; +} diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/test.desc new file mode 100644 index 00000000000..e15cedd3f15 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/test.desc @@ -0,0 +1,5 @@ +CORE +main.c +--show --variable-sensitivity --interval-values --arrays +main::1::second_value \(\) -> \[00000000000000000000000000000010, 00000000000000000000000000000010\] +main::1::second_value_after_write \(\) -> \[00000000000000000000000000001010, 00000000000000000000000000001010\] \ No newline at end of file diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/main.c new file mode 100644 index 00000000000..04976fc9c51 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/main.c @@ -0,0 +1,27 @@ +int main(void) +{ + int arr[] = {1,2,3}; + int ix; + if(ix) { + ix = 0; + } else { + ix = 2; + } + // ix is between 0 and 2 + // so this is between 1 and 3 + int arr_at_ix = arr[ix]; + int write_ix; + if(write_ix) { + write_ix = 0; + } else { + write_ix = 1; + } + arr[write_ix] = 4; + int arr_0_after_write = arr[0]; + int arr_1_after_write = arr[1]; + // We can't write to arr[2] + // because write_ix is between 0 and 1 + // so this should be unchanged + int arr_2_after_write = arr[2]; + return 0; +} diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/test.desc new file mode 100644 index 00000000000..c342ebc519e --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/test.desc @@ -0,0 +1,7 @@ +CORE +main.c +--show --variable-sensitivity --interval-values --arrays +main::1::arr_at_ix \(\) -> \[00000000000000000000000000000001, 00000000000000000000000000000011\] +main::1::arr_0_after_write \(\) -> \[00000000000000000000000000000001, 00000000000000000000000000000100\] +main::1::arr_1_after_write \(\) -> \[00000000000000000000000000000010, 00000000000000000000000000000100\] +main::1::arr_2_after_write \(\) -> \[00000000000000000000000000000011, 00000000000000000000000000000011\] \ No newline at end of file diff --git a/src/analyses/Makefile b/src/analyses/Makefile index fc7a5fdf918..64249f0c8bc 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -53,6 +53,7 @@ SRC = ai.cpp \ variable-sensitivity/data_dependency_context.cpp \ variable-sensitivity/variable_sensitivity_dependence_graph.cpp \ variable-sensitivity/interval_abstract_value.cpp \ + variable-sensitivity/interval_array_abstract_object.cpp \ # Empty last line INCLUDES= -I .. diff --git a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp new file mode 100644 index 00000000000..84e8f006a8f --- /dev/null +++ b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp @@ -0,0 +1,104 @@ +/*******************************************************************\ + +Module: analyses variable-sensitivity interval-values arrays + +Author: Diffblue Ltd. + +\*******************************************************************/ + +#include +#include "abstract_enviroment.h" +#include "interval_array_abstract_object.h" + +interval_array_abstract_objectt::interval_array_abstract_objectt(typet type) : constant_array_abstract_objectt(type) { + +} + +interval_array_abstract_objectt::interval_array_abstract_objectt(typet type, bool top, bool bottom) + : constant_array_abstract_objectt(type, top, bottom) { + +} + +interval_array_abstract_objectt::interval_array_abstract_objectt(const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) + : constant_array_abstract_objectt(expr, environment, ns) {} + +sharing_ptrt +interval_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 { + auto evaluated_index = environment.eval(index_expr.index(), ns); + auto evaluated_index_const = evaluated_index->to_constant(); + if(evaluated_index_const.id() == ID_constant) { + return constant_array_abstract_objectt::write_index(environment, ns, stack, index_expr, value, merging_write); + } else if(evaluated_index_const.id() == ID_constant_interval) { + auto const& index_interval = to_constant_interval_expr(evaluated_index_const); + if(index_interval.is_single_value_interval()) { + return constant_array_abstract_objectt::write_index(environment, ns, stack, + index_exprt(index_expr.array(), index_interval.get_lower()), + value, merging_write); + } + else if(!index_interval.is_top() && !index_interval.is_bottom()) { + auto ix = index_interval.get_lower(); + auto interval_end = index_interval.get_upper(); + sharing_ptrt result = shared_from_this(); + while(simplify_expr(binary_predicate_exprt(ix, ID_gt, interval_end), ns).is_false()) { + auto array_after_write_at_index = constant_array_abstract_objectt::write_index( + environment, ns, stack, index_exprt(index_expr.index(), ix), value, merging_write); + bool dontcare; + result = abstract_objectt::merge(result, array_after_write_at_index, dontcare); + ix = simplify_expr(plus_exprt(ix, constant_exprt("1", ix.type())), ns); + } + return std::dynamic_pointer_cast(result); + } + } + return std::dynamic_pointer_cast(make_top()); +} + +abstract_object_pointert +interval_array_abstract_objectt::read_index(const abstract_environmentt &env, const index_exprt &index, + const namespacet &ns) const { + auto evaluated_index = env.eval(index.index(), ns); + auto evaluated_index_const = evaluated_index->to_constant(); + if(evaluated_index_const.id() == ID_constant) { + UNREACHABLE; + return constant_array_abstract_objectt::read_index(env,index,ns); + } else if(evaluated_index_const.id() == ID_constant_interval) { + auto const& index_interval = to_constant_interval_expr(evaluated_index_const); + if(!index_interval.is_top() && !index_interval.is_bottom()) + { + auto ix = index_interval.get_lower(); + auto interval_end = index_interval.get_upper(); + abstract_object_pointert value; + while(simplify_expr(binary_relation_exprt(ix, ID_gt, interval_end), ns).is_false()) + { + auto value_at_index = constant_array_abstract_objectt::read_index(env, index_exprt(index.array(), ix), ns); + if(value != nullptr) { + bool dont_care; + value = abstract_objectt::merge(value, value_at_index, dont_care); + } else { + value = value_at_index; + } + ix = simplify_expr(plus_exprt(ix, constant_exprt("1", ix.type())), ns); + } + return value; + } + } + return env.abstract_object_factory(type().subtype(), ns); +} + +bool interval_array_abstract_objectt::eval_index(const index_exprt &index, const abstract_environmentt &env, + const namespacet &ns, mp_integer &out_index) const { + auto index_value = env.eval(index.index(), ns); + auto index_const = index_value->to_constant(); + if(index_const.id() != ID_constant_interval) { + return constant_array_abstract_objectt::eval_index(index, env, ns, out_index); + } + auto index_interval = to_constant_interval_expr(index_const); + if(index_interval.is_single_value_interval()) { + out_index = numeric_cast_v(index_interval.get_lower()); + return true; + } + return false; +} diff --git a/src/analyses/variable-sensitivity/interval_array_abstract_object.h b/src/analyses/variable-sensitivity/interval_array_abstract_object.h new file mode 100644 index 00000000000..73053ab4b24 --- /dev/null +++ b/src/analyses/variable-sensitivity/interval_array_abstract_object.h @@ -0,0 +1,38 @@ +/*******************************************************************\ + +Module: analyses variable-sensitivity interval-values arrays + +Author: Diffblue Ltd. + +\*******************************************************************/ + +#ifndef PROJECT_INTERVAL_ARRAY_ABSTRACT_OBJECTT_H +#define PROJECT_INTERVAL_ARRAY_ABSTRACT_OBJECTT_H + + +#include "constant_array_abstract_object.h" + +class interval_array_abstract_objectt : public constant_array_abstract_objectt { +public: + explicit interval_array_abstract_objectt(typet type); + + interval_array_abstract_objectt(typet type, bool top, bool bottom); + + interval_array_abstract_objectt(const exprt &expr, const abstract_environmentt &environment, const namespacet &ns); + +protected: + CLONE + abstract_object_pointert + read_index(const abstract_environmentt &env, const index_exprt &index, const namespacet &ns) const override; + + 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; + + bool eval_index(const index_exprt &index, const abstract_environmentt &env, const namespacet &ns, + mp_integer &out_index) const override; + +}; + + +#endif //PROJECT_INTERVAL_ARRAY_ABSTRACT_OBJECTT_H diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index fa19566956e..e4b50bdf677 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -7,6 +7,7 @@ \*******************************************************************/ #include "variable_sensitivity_object_factory.h" #include "util/namespace.h" +#include "interval_array_abstract_object.h" variable_sensitivity_object_factoryt variable_sensitivity_object_factoryt::s_instance; @@ -106,7 +107,10 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: return initialize_abstract_object( followed_type, top, bottom, e, environment, ns); case ARRAY_SENSITIVE: - return initialize_abstract_object( + return has_interval + ? initialize_abstract_object( + followed_type, top, bottom, e, environment, ns) + : initialize_abstract_object( followed_type, top, bottom, e, environment, ns); case ARRAY_INSENSITIVE: return initialize_abstract_object( From d4e3603a70e73c03be2dcad8a756881689eb8fa5 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Tue, 22 May 2018 17:04:57 +0100 Subject: [PATCH 238/342] Clang format --- .../main.c | 2 +- .../main.c | 16 +- .../variable-sensitivity/abstract_object.cpp | 5 + .../variable-sensitivity/abstract_object.h | 2 + .../context_abstract_object.cpp | 5 + .../context_abstract_object.h | 2 + .../interval_abstract_value.cpp | 40 ++-- .../interval_abstract_value.h | 2 + .../interval_array_abstract_object.cpp | 178 +++++++++++------- .../interval_array_abstract_object.h | 38 ++-- .../variable_sensitivity_object_factory.cpp | 10 +- 11 files changed, 193 insertions(+), 107 deletions(-) diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/main.c index 93ec0d18148..41aa58a0e10 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/main.c +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/main.c @@ -1,6 +1,6 @@ int main(void) { - int arr[] = {1,2,3}; + int arr[] = {1, 2, 3}; int second_value = arr[1]; arr[1] = 10; int second_value_after_write = arr[1]; diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/main.c index 04976fc9c51..12756805712 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/main.c +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/main.c @@ -1,19 +1,25 @@ int main(void) { - int arr[] = {1,2,3}; + int arr[] = {1, 2, 3}; int ix; - if(ix) { + if(ix) + { ix = 0; - } else { + } + else + { ix = 2; } // ix is between 0 and 2 // so this is between 1 and 3 int arr_at_ix = arr[ix]; int write_ix; - if(write_ix) { + if(write_ix) + { write_ix = 0; - } else { + } + else + { write_ix = 1; } arr[write_ix] = 4; diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index acd37f8ff97..b10cb07d2d9 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -457,3 +457,8 @@ void abstract_objectt::dump_map_diff( } out << "}"; } + +abstract_object_pointert abstract_objectt::unwrap_context() const +{ + return shared_from_this(); +} diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 03a571bd742..86812f3a097 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -176,6 +176,8 @@ class abstract_objectt:public std::enable_shared_from_this return clone; } + virtual abstract_object_pointert unwrap_context() const; + /** * Pure virtual interface required of a client that can apply a copy-on-write * operation to a given abstract_object_pointert. diff --git a/src/analyses/variable-sensitivity/context_abstract_object.cpp b/src/analyses/variable-sensitivity/context_abstract_object.cpp index 796c4e74ef9..4d87a4df878 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/context_abstract_object.cpp @@ -163,3 +163,8 @@ bool context_abstract_objectt::has_been_modified( return this->child_abstract_object.get() != before_context->child_abstract_object.get(); } + +abstract_object_pointert context_abstract_objectt::unwrap_context() const +{ + return child_abstract_object->unwrap_context(); +} diff --git a/src/analyses/variable-sensitivity/context_abstract_object.h b/src/analyses/variable-sensitivity/context_abstract_object.h index 80487386878..3b011c38a06 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.h +++ b/src/analyses/variable-sensitivity/context_abstract_object.h @@ -82,6 +82,8 @@ class context_abstract_objectt: public abstract_objectt std::ostream &out, const class ai_baset &ai, const namespacet &ns) const override; + abstract_object_pointert unwrap_context() const override; + protected: CLONE diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index 228a4508cb6..5e4ab76749f 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -15,31 +15,39 @@ #include "interval_abstract_value.h" -static inline exprt look_through_casts(exprt e) { - while(e.id() == ID_typecast) { +static inline exprt look_through_casts(exprt e) +{ + while(e.id() == ID_typecast) + { e = e.op0(); } return e; } -static inline constant_interval_exprt make_interval_expr(exprt e) { +static inline constant_interval_exprt make_interval_expr(exprt e) +{ e = look_through_casts(e); - if(e.id() == ID_constant_interval) { + if(e.id() == ID_constant_interval) + { return to_constant_interval_expr(e); - } else if(e.id() == ID_constant) { + } + else if(e.id() == ID_constant) + { return constant_interval_exprt(e, e); - } else { + } + else + { // not directly representable, so just return TOP return constant_interval_exprt(e.type()); } } -interval_abstract_valuet::interval_abstract_valuet(typet t): - abstract_valuet(t), interval(t) +interval_abstract_valuet::interval_abstract_valuet(typet t) + : abstract_valuet(t), interval(t) {} -interval_abstract_valuet::interval_abstract_valuet(typet t, bool tp, bool bttm): - abstract_valuet(t, tp, bttm), interval(t) +interval_abstract_valuet::interval_abstract_valuet(typet t, bool tp, bool bttm) + : abstract_valuet(t, tp, bttm), interval(t) {} interval_abstract_valuet::interval_abstract_valuet( @@ -52,7 +60,6 @@ interval_abstract_valuet::interval_abstract_valuet( exprt interval_abstract_valuet::to_constant() const { return abstract_objectt::to_constant(); - #if 0 if(!is_top() && !is_bottom()) { @@ -225,8 +232,10 @@ abstract_object_pointert interval_abstract_valuet::merge_intervals( } } -interval_abstract_valuet::interval_abstract_valuet(const exprt e, const abstract_environmentt &environment, - const namespacet &ns) +interval_abstract_valuet::interval_abstract_valuet( + const exprt e, + const abstract_environmentt &environment, + const namespacet &ns) : interval_abstract_valuet(make_interval_expr(e)) {} @@ -238,3 +247,8 @@ interval_abstract_valuet::interval_abstract_valuet( merge_count(merge_count) { } + +const constant_interval_exprt &interval_abstract_valuet::get_interval() const +{ + return interval; +} diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h index b94514ded86..f3ee3aa9890 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.h +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -51,6 +51,8 @@ class interval_abstract_valuet:public abstract_valuet const class ai_baset &ai, const class namespacet &ns) const override; + const constant_interval_exprt &get_interval() const; + protected: CLONE virtual abstract_object_pointert merge( diff --git a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp index 84e8f006a8f..cad147652fa 100644 --- a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp @@ -6,97 +6,137 @@ Author: Diffblue Ltd. \*******************************************************************/ -#include -#include "abstract_enviroment.h" #include "interval_array_abstract_object.h" +#include "abstract_enviroment.h" +#include "interval_abstract_value.h" +#include -interval_array_abstract_objectt::interval_array_abstract_objectt(typet type) : constant_array_abstract_objectt(type) { - +interval_array_abstract_objectt::interval_array_abstract_objectt(typet type) + : constant_array_abstract_objectt(type) +{ } -interval_array_abstract_objectt::interval_array_abstract_objectt(typet type, bool top, bool bottom) - : constant_array_abstract_objectt(type, top, bottom) { +interval_array_abstract_objectt::interval_array_abstract_objectt( + typet type, + bool top, + bool bottom) + : constant_array_abstract_objectt(type, top, bottom) +{ +} +interval_array_abstract_objectt::interval_array_abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) + : constant_array_abstract_objectt(expr, environment, ns) +{ } -interval_array_abstract_objectt::interval_array_abstract_objectt(const exprt &expr, - const abstract_environmentt &environment, - const namespacet &ns) - : constant_array_abstract_objectt(expr, environment, ns) {} +static constant_interval_exprt eval_and_get_as_interval( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) +{ + auto evaluated_index = environment.eval(expr, ns); + auto evaluated_index_interval = + std::dynamic_pointer_cast( + evaluated_index->unwrap_context()); + INVARIANT( + evaluated_index_interval != nullptr, + "Expecting expression to evaluate to index"); + return evaluated_index_interval->get_interval(); +} sharing_ptrt -interval_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 { - auto evaluated_index = environment.eval(index_expr.index(), ns); - auto evaluated_index_const = evaluated_index->to_constant(); - if(evaluated_index_const.id() == ID_constant) { - return constant_array_abstract_objectt::write_index(environment, ns, stack, index_expr, value, merging_write); - } else if(evaluated_index_const.id() == ID_constant_interval) { - auto const& index_interval = to_constant_interval_expr(evaluated_index_const); - if(index_interval.is_single_value_interval()) { - return constant_array_abstract_objectt::write_index(environment, ns, stack, - index_exprt(index_expr.array(), index_interval.get_lower()), - value, merging_write); - } - else if(!index_interval.is_top() && !index_interval.is_bottom()) { - auto ix = index_interval.get_lower(); - auto interval_end = index_interval.get_upper(); - sharing_ptrt result = shared_from_this(); - while(simplify_expr(binary_predicate_exprt(ix, ID_gt, interval_end), ns).is_false()) { - auto array_after_write_at_index = constant_array_abstract_objectt::write_index( - environment, ns, stack, index_exprt(index_expr.index(), ix), value, merging_write); - bool dontcare; - result = abstract_objectt::merge(result, array_after_write_at_index, dontcare); - ix = simplify_expr(plus_exprt(ix, constant_exprt("1", ix.type())), ns); - } - return std::dynamic_pointer_cast(result); +interval_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 +{ + auto evaluated_index_interval = + eval_and_get_as_interval(index_expr.index(), environment, ns); + if(evaluated_index_interval.is_single_value_interval()) + { + return constant_array_abstract_objectt::write_index( + environment, + ns, + stack, + index_exprt(index_expr.array(), evaluated_index_interval.get_lower()), + value, + merging_write); + } + else if( + !evaluated_index_interval.is_top() && !evaluated_index_interval.is_bottom()) + { + auto ix = evaluated_index_interval.get_lower(); + auto interval_end = evaluated_index_interval.get_upper(); + sharing_ptrt result = shared_from_this(); + while(simplify_expr(binary_predicate_exprt(ix, ID_gt, interval_end), ns) + .is_false()) + { + auto array_after_write_at_index = + constant_array_abstract_objectt::write_index( + environment, + ns, + stack, + index_exprt(index_expr.index(), ix), + value, + merging_write); + bool dontcare; + result = + abstract_objectt::merge(result, array_after_write_at_index, dontcare); + ix = simplify_expr(plus_exprt(ix, constant_exprt("1", ix.type())), ns); } + return std::dynamic_pointer_cast(result); } return std::dynamic_pointer_cast(make_top()); } -abstract_object_pointert -interval_array_abstract_objectt::read_index(const abstract_environmentt &env, const index_exprt &index, - const namespacet &ns) const { - auto evaluated_index = env.eval(index.index(), ns); - auto evaluated_index_const = evaluated_index->to_constant(); - if(evaluated_index_const.id() == ID_constant) { - UNREACHABLE; - return constant_array_abstract_objectt::read_index(env,index,ns); - } else if(evaluated_index_const.id() == ID_constant_interval) { - auto const& index_interval = to_constant_interval_expr(evaluated_index_const); - if(!index_interval.is_top() && !index_interval.is_bottom()) +abstract_object_pointert interval_array_abstract_objectt::read_index( + const abstract_environmentt &env, + const index_exprt &index, + const namespacet &ns) const +{ + auto evaluated_index_value = eval_and_get_as_interval(index.index(), env, ns); + auto const &index_interval = to_constant_interval_expr(evaluated_index_value); + if(!index_interval.is_top() && !index_interval.is_bottom()) + { + auto ix = index_interval.get_lower(); + auto interval_end = index_interval.get_upper(); + abstract_object_pointert value; + while(simplify_expr(binary_relation_exprt(ix, ID_gt, interval_end), ns) + .is_false()) { - auto ix = index_interval.get_lower(); - auto interval_end = index_interval.get_upper(); - abstract_object_pointert value; - while(simplify_expr(binary_relation_exprt(ix, ID_gt, interval_end), ns).is_false()) + auto value_at_index = constant_array_abstract_objectt::read_index( + env, index_exprt(index.array(), ix), ns); + if(value != nullptr) { - auto value_at_index = constant_array_abstract_objectt::read_index(env, index_exprt(index.array(), ix), ns); - if(value != nullptr) { - bool dont_care; - value = abstract_objectt::merge(value, value_at_index, dont_care); - } else { - value = value_at_index; - } - ix = simplify_expr(plus_exprt(ix, constant_exprt("1", ix.type())), ns); + bool dont_care; + value = abstract_objectt::merge(value, value_at_index, dont_care); } - return value; + else + { + value = value_at_index; + } + ix = simplify_expr(plus_exprt(ix, constant_exprt("1", ix.type())), ns); } + return value; } return env.abstract_object_factory(type().subtype(), ns); } -bool interval_array_abstract_objectt::eval_index(const index_exprt &index, const abstract_environmentt &env, - const namespacet &ns, mp_integer &out_index) const { - auto index_value = env.eval(index.index(), ns); - auto index_const = index_value->to_constant(); - if(index_const.id() != ID_constant_interval) { - return constant_array_abstract_objectt::eval_index(index, env, ns, out_index); - } - auto index_interval = to_constant_interval_expr(index_const); - if(index_interval.is_single_value_interval()) { +bool interval_array_abstract_objectt::eval_index( + const index_exprt &index, + const abstract_environmentt &env, + const namespacet &ns, + mp_integer &out_index) const +{ + auto index_interval = eval_and_get_as_interval(index.index(), env, ns); + if(index_interval.is_single_value_interval()) + { out_index = numeric_cast_v(index_interval.get_lower()); return true; } diff --git a/src/analyses/variable-sensitivity/interval_array_abstract_object.h b/src/analyses/variable-sensitivity/interval_array_abstract_object.h index 73053ab4b24..0b083fad8ac 100644 --- a/src/analyses/variable-sensitivity/interval_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/interval_array_abstract_object.h @@ -9,30 +9,40 @@ Author: Diffblue Ltd. #ifndef PROJECT_INTERVAL_ARRAY_ABSTRACT_OBJECTT_H #define PROJECT_INTERVAL_ARRAY_ABSTRACT_OBJECTT_H - #include "constant_array_abstract_object.h" -class interval_array_abstract_objectt : public constant_array_abstract_objectt { +class interval_array_abstract_objectt : public constant_array_abstract_objectt +{ public: explicit interval_array_abstract_objectt(typet type); interval_array_abstract_objectt(typet type, bool top, bool bottom); - interval_array_abstract_objectt(const exprt &expr, const abstract_environmentt &environment, const namespacet &ns); + interval_array_abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); protected: CLONE - abstract_object_pointert - read_index(const abstract_environmentt &env, const index_exprt &index, const namespacet &ns) const override; - - 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; - - bool eval_index(const index_exprt &index, const abstract_environmentt &env, const namespacet &ns, - mp_integer &out_index) const override; - + abstract_object_pointert read_index( + const abstract_environmentt &env, + const index_exprt &index, + const namespacet &ns) const override; + + 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; + + bool eval_index( + const index_exprt &index, + const abstract_environmentt &env, + const namespacet &ns, + mp_integer &out_index) const override; }; - #endif //PROJECT_INTERVAL_ARRAY_ABSTRACT_OBJECTT_H diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index e4b50bdf677..88ba88f7e21 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -6,8 +6,8 @@ \*******************************************************************/ #include "variable_sensitivity_object_factory.h" -#include "util/namespace.h" #include "interval_array_abstract_object.h" +#include "util/namespace.h" variable_sensitivity_object_factoryt variable_sensitivity_object_factoryt::s_instance; @@ -108,10 +108,10 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: followed_type, top, bottom, e, environment, ns); case ARRAY_SENSITIVE: return has_interval - ? initialize_abstract_object( - followed_type, top, bottom, e, environment, ns) - : initialize_abstract_object( - followed_type, top, bottom, e, environment, ns); + ? initialize_abstract_object( + followed_type, top, bottom, e, environment, ns) + : initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); case ARRAY_INSENSITIVE: return initialize_abstract_object( followed_type, top, bottom, e, environment, ns); From 28f59b1013d373f275306d485c15b002125778c0 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 30 May 2018 15:28:42 +0100 Subject: [PATCH 239/342] Return top in case of min/max indices in interval arrays There's little else useful we can do in these cases. Note: It might be worth to also return top if the index is (or might be) out of bounds for the array type, but this is inconsistent with how it currently works for constant_array_abstract_objectt --- .../interval_array_abstract_object.cpp | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp index cad147652fa..ccbc57072d5 100644 --- a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp @@ -56,23 +56,26 @@ interval_array_abstract_objectt::write_index( const abstract_object_pointert value, bool merging_write) const { - auto evaluated_index_interval = + auto index_interval = eval_and_get_as_interval(index_expr.index(), environment, ns); - if(evaluated_index_interval.is_single_value_interval()) + + if(index_interval.is_single_value_interval()) { return constant_array_abstract_objectt::write_index( environment, ns, stack, - index_exprt(index_expr.array(), evaluated_index_interval.get_lower()), + index_exprt(index_expr.array(), index_interval.get_lower()), value, merging_write); } else if( - !evaluated_index_interval.is_top() && !evaluated_index_interval.is_bottom()) + !index_interval.is_top() && !index_interval.is_bottom() && + index_interval.get_lower().id() != ID_min && + index_interval.get_upper().id() != ID_max) { - auto ix = evaluated_index_interval.get_lower(); - auto interval_end = evaluated_index_interval.get_upper(); + auto ix = index_interval.get_lower(); + auto interval_end = index_interval.get_upper(); sharing_ptrt result = shared_from_this(); while(simplify_expr(binary_predicate_exprt(ix, ID_gt, interval_end), ns) .is_false()) @@ -102,7 +105,10 @@ abstract_object_pointert interval_array_abstract_objectt::read_index( { auto evaluated_index_value = eval_and_get_as_interval(index.index(), env, ns); auto const &index_interval = to_constant_interval_expr(evaluated_index_value); - if(!index_interval.is_top() && !index_interval.is_bottom()) + if( + !index_interval.is_top() && !index_interval.is_bottom() && + index_interval.get_lower().id() != ID_min && + index_interval.get_upper().id() != ID_max) { auto ix = index_interval.get_lower(); auto interval_end = index_interval.get_upper(); From f36936a69d865c963351d3c46d7ff0443a841aba Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 30 May 2018 17:38:36 +0100 Subject: [PATCH 240/342] Exit loops in interval arrays early if result becomes top --- .../variable-sensitivity/interval_array_abstract_object.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp index ccbc57072d5..e535b87cc25 100644 --- a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp @@ -77,7 +77,7 @@ interval_array_abstract_objectt::write_index( auto ix = index_interval.get_lower(); auto interval_end = index_interval.get_upper(); sharing_ptrt result = shared_from_this(); - while(simplify_expr(binary_predicate_exprt(ix, ID_gt, interval_end), ns) + while(!result->is_top() && simplify_expr(binary_predicate_exprt(ix, ID_gt, interval_end), ns) .is_false()) { auto array_after_write_at_index = @@ -113,7 +113,7 @@ abstract_object_pointert interval_array_abstract_objectt::read_index( auto ix = index_interval.get_lower(); auto interval_end = index_interval.get_upper(); abstract_object_pointert value; - while(simplify_expr(binary_relation_exprt(ix, ID_gt, interval_end), ns) + while((!value || !value->is_top()) && simplify_expr(binary_relation_exprt(ix, ID_gt, interval_end), ns) .is_false()) { auto value_at_index = constant_array_abstract_objectt::read_index( From 2a1459d4c3d6ec58942a45f47f2392138a48811d Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 30 May 2018 17:48:25 +0100 Subject: [PATCH 241/342] Use from_integer instead of constant_exprt constructor --- .../variable-sensitivity/interval_array_abstract_object.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp index e535b87cc25..340b11fb2c9 100644 --- a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp @@ -91,7 +91,7 @@ interval_array_abstract_objectt::write_index( bool dontcare; result = abstract_objectt::merge(result, array_after_write_at_index, dontcare); - ix = simplify_expr(plus_exprt(ix, constant_exprt("1", ix.type())), ns); + ix = simplify_expr(plus_exprt(ix, from_integer(1, ix.type())), ns); } return std::dynamic_pointer_cast(result); } @@ -127,7 +127,7 @@ abstract_object_pointert interval_array_abstract_objectt::read_index( { value = value_at_index; } - ix = simplify_expr(plus_exprt(ix, constant_exprt("1", ix.type())), ns); + ix = simplify_expr(plus_exprt(ix, from_integer(1, ix.type())), ns); } return value; } From 7ee14aea42720470c38efcca1afa8cf3a9c0d71d Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Thu, 31 May 2018 15:08:45 +0100 Subject: [PATCH 242/342] Adapt dependence graph regression test to new output format --- .../test.desc | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc index 22222bd4c93..cce09a2a906 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc @@ -3,35 +3,35 @@ main.c file1.c file2.c --dependence-graph-vs --structs --arrays --show EXIT=0 SIGNAL=0 -^Data dependencies: 53$ -^Data dependencies: 53$ -^Data dependencies: 1, 53$ -^Data dependencies: 4, 53$ -^Data dependencies: 1, 4, 53$ -^Data dependencies: 48$ -^Data dependencies: 48$ -^Data dependencies: 10, 48$ -^Data dependencies: 13, 48$ -^Data dependencies: 10, 13, 48$ -^Data dependencies: 19$ -^Data dependencies: 18$ -^Data dependencies: 19$ -^Data dependencies: 19, 20, 22$ -^Data dependencies: 1, 53, 57$ -^Data dependencies: 4, 53, 60$ -^Data dependencies: 1, 4, 53, 57, 60$ -^Data dependencies: 10, 48, 68$ -^Data dependencies: 13, 48, 71$ -^Data dependencies: 10, 13, 48, 68, 71$ -^Data dependencies: 1, 53$ -^Data dependencies: 4, 53$ -^Data dependencies: 1, 53, 57$ -^Data dependencies: 4, 53, 60$ -^Data dependencies: 1, 4, 53, 57, 60$ -^Data dependencies: 10, 48$ -^Data dependencies: 13, 48$ -^Data dependencies: 10, 48, 68$ -^Data dependencies: 13, 48, 71$ -^Data dependencies: 10, 13, 48, 68, 71$ +^Data dependencies: 53 \[st.a\]$ +^Data dependencies: 53 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 53 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 53 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\]$ +^Data dependencies: 48 \[ar\[\(signed long int\)0\]\]$ +^Data dependencies: 48 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\]$ +^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\]$ +^Data dependencies: 19 \[arr\[\(signed long int\)1\]\]$ +^Data dependencies: 18 \[arr\[\(signed long int\)0\]\]$ +^Data dependencies: 19 \[arr\[\(signed long int\)1\]\]$ +^Data dependencies: 19 \[arr\[\(signed long int\)2\]\], 20 \[arr\[\(signed long int\)2\]\], 22 \[arr\[\(signed long int\)2\]\]$ +^Data dependencies: 1 \[st.a\], 53 \[st.a\], 57 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 53 \[st.b\], 60 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\], 57 \[st.a\], 60 \[st.b\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\], 68 \[ar\[\(signed long int\)0\]\]$ +^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\], 71 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 68 \[ar\[\(signed long int\)0\]\], 71 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 1 \[st.a\], 53 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 53 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 53 \[st.a\], 57 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 53 \[st.b\], 60 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\], 57 \[st.a\], 60 \[st.b\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\]$ +^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\], 68 \[ar\[\(signed long int\)0\]\]$ +^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\], 71 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 68 \[ar\[\(signed long int\)0\]\], 71 \[ar\[\(signed long int\)1\]\]$ -- ^warning: ignoring From f5e6b12f53ed52e4a55dd36c6d385942449a0cfb Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 6 Jul 2018 11:20:29 +0100 Subject: [PATCH 243/342] Fixups to enable building after rebase --- src/analyses/variable-sensitivity/constant_abstract_value.h | 2 +- src/analyses/variable-sensitivity/context_abstract_object.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 45479f02deb..082cc9e506a 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -33,7 +33,7 @@ class constant_abstract_valuet:public abstract_valuet const exprt &expr, const std::vector &operands, const abstract_environmentt &environment, - const namespacet &ns) const; + const namespacet &ns) const override; virtual exprt to_constant() const override; diff --git a/src/analyses/variable-sensitivity/context_abstract_object.h b/src/analyses/variable-sensitivity/context_abstract_object.h index 3b011c38a06..ecaf8afff84 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.h +++ b/src/analyses/variable-sensitivity/context_abstract_object.h @@ -76,7 +76,7 @@ class context_abstract_objectt: public abstract_objectt const exprt &expr, const std::vector &operands, const abstract_environmentt &environment, - const namespacet &ns) const; + const namespacet &ns) const override; virtual void output( std::ostream &out, const class ai_baset &ai, const namespacet &ns) const From 66ae4349f3dd7cf840a2b1ae3d62f0a7023a343d Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Wed, 4 Jul 2018 11:26:41 +0100 Subject: [PATCH 244/342] Add function to get statistics about variable sensitivity domain Currently, only number of interval objects and number of single-value intervals are tracked, but this could easily be changed --- .../abstract_enviroment.cpp | 18 ++++++++++++++++++ .../variable-sensitivity/abstract_enviroment.h | 6 ++++-- .../variable-sensitivity/abstract_object.cpp | 11 +++++++++++ .../variable-sensitivity/abstract_object.h | 9 ++++++++- .../abstract_object_statistics.h | 12 ++++++++++++ .../constant_array_abstract_object.cpp | 18 ++++++++++++++++++ .../constant_array_abstract_object.h | 6 ++++++ .../constant_pointer_abstract_object.cpp | 14 ++++++++++++++ .../constant_pointer_abstract_object.h | 6 ++++++ .../context_abstract_object.cpp | 13 +++++++++++++ .../context_abstract_object.h | 6 ++++++ .../full_struct_abstract_object.cpp | 18 ++++++++++++++++++ .../full_struct_abstract_object.h | 6 ++++++ .../interval_abstract_value.cpp | 14 ++++++++++++++ .../interval_abstract_value.h | 7 +++++++ 15 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 src/analyses/variable-sensitivity/abstract_object_statistics.h diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 38e091dc4e0..8f1529353ef 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -20,6 +20,7 @@ #include #include "abstract_enviroment.h" +#include "abstract_object_statistics.h" #ifdef DEBUG #include @@ -737,3 +738,20 @@ std::vector abstract_environmentt::modified_symbols( } return symbols_diff; } + +abstract_object_statisticst +abstract_environmentt::gather_statistics(const namespacet &ns) const +{ + abstract_object_statisticst statistics = {}; + decltype(map)::viewt view; + map.get_view(view); + abstract_object_visitedt visited; + for(auto const &object : view) + { + if(visited.find(object.second) == visited.end()) + { + object.second->get_statistics(statistics, visited, *this, ns); + } + } + return statistics; +} diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index f41480e1390..bb186580999 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -15,10 +15,10 @@ #include #include -#include -#include +#include "abstract_object_statistics.h" #include #include +#include class abstract_environmentt { @@ -73,6 +73,8 @@ class abstract_environmentt const abstract_environmentt &first, const abstract_environmentt &second); + abstract_object_statisticst gather_statistics(const namespacet &ns) const; + protected: bool bottom; diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index b10cb07d2d9..cb3de4d05eb 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -462,3 +462,14 @@ abstract_object_pointert abstract_objectt::unwrap_context() const { return shared_from_this(); } + +void abstract_objectt::get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const +{ + const auto &this_ptr = shared_from_this(); + PRECONDITION(visited.find(this_ptr) == visited.end()); + visited.insert(this_ptr); +} diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 86812f3a097..02602a3bf8f 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -36,13 +36,13 @@ #include #include #include +#include "abstract_object_statistics.h" class typet; class constant_exprt; class abstract_environmentt; class namespacet; - #define CLONE \ virtual internal_abstract_object_pointert mutable_clone() const override \ { \ @@ -75,6 +75,7 @@ template using sharing_ptrt=std::shared_ptr; // NOLINT(*) typedef sharing_ptrt abstract_object_pointert; +using abstract_object_visitedt = std::set; class abstract_objectt:public std::enable_shared_from_this { @@ -92,6 +93,12 @@ class abstract_objectt:public std::enable_shared_from_this virtual bool is_top() const; virtual bool is_bottom() const; + virtual void get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const; + // Interface for transforms virtual abstract_object_pointert expression_transform( const exprt &expr, diff --git a/src/analyses/variable-sensitivity/abstract_object_statistics.h b/src/analyses/variable-sensitivity/abstract_object_statistics.h new file mode 100644 index 00000000000..fbae4dee548 --- /dev/null +++ b/src/analyses/variable-sensitivity/abstract_object_statistics.h @@ -0,0 +1,12 @@ +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_STATISTICS_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_STATISTICS_H + +#include + +struct abstract_object_statisticst +{ + std::size_t number_of_interval_abstract_objects; + std::size_t number_of_single_value_intervals; +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_STATISTICS_H diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 19972c96a40..4aa508d46b3 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -532,3 +532,21 @@ constant_array_abstract_objectt::visit_sub_elements( return shared_from_this(); } } + +void constant_array_abstract_objectt::get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const +{ + array_abstract_objectt::get_statistics(statistics, visited, env, ns); + shared_array_mapt::viewt view; + map.get_view(view); + for(auto const &object : view) + { + if(visited.find(object.second) == visited.end()) + { + object.second->get_statistics(statistics, visited, env, ns); + } + } +} diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index f4c4829ae68..8d68f0015cd 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -38,6 +38,12 @@ class constant_array_abstract_objectt:public array_abstract_objectt virtual abstract_object_pointert visit_sub_elements( const abstract_object_visitort &visitor) const override; + void get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const override; + protected: CLONE diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index cb640b93b15..69513c7987f 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -360,3 +360,17 @@ sharing_ptrt return std::dynamic_pointer_cast(shared_from_this()); } } + +void constant_pointer_abstract_objectt::get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const +{ + pointer_abstract_objectt::get_statistics(statistics, visited, env, ns); + // don't bother following nullptr + if(!is_top() && !is_bottom() && !value_stack.is_top_value()) + { + read_dereference(env, ns)->get_statistics(statistics, visited, env, ns); + } +} diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index d3ccabe9771..399797396fe 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -48,6 +48,12 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt const abstract_object_pointert value, bool merging_write) const override; + void get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const override; + protected: virtual abstract_object_pointert merge( abstract_object_pointert op1) const override; diff --git a/src/analyses/variable-sensitivity/context_abstract_object.cpp b/src/analyses/variable-sensitivity/context_abstract_object.cpp index 4d87a4df878..0eb0765209e 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/context_abstract_object.cpp @@ -168,3 +168,16 @@ abstract_object_pointert context_abstract_objectt::unwrap_context() const { return child_abstract_object->unwrap_context(); } + +void context_abstract_objectt::get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const +{ + abstract_objectt::get_statistics(statistics, visited, env, ns); + if(visited.find(child_abstract_object) == visited.end()) + { + child_abstract_object->get_statistics(statistics, visited, env, ns); + } +} diff --git a/src/analyses/variable-sensitivity/context_abstract_object.h b/src/analyses/variable-sensitivity/context_abstract_object.h index ecaf8afff84..a9fff3029a0 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.h +++ b/src/analyses/variable-sensitivity/context_abstract_object.h @@ -84,6 +84,12 @@ class context_abstract_objectt: public abstract_objectt abstract_object_pointert unwrap_context() const override; + void get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const override; + protected: CLONE diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 372d3df487b..6a6599d0efe 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -479,3 +479,21 @@ abstract_object_pointert full_struct_abstract_objectt::visit_sub_elements( return shared_from_this(); } } + +void full_struct_abstract_objectt::get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const +{ + struct_abstract_objectt::get_statistics(statistics, visited, env, ns); + shared_struct_mapt::viewt view; + map.get_view(view); + for(auto const &object : view) + { + if(visited.find(object.second) == visited.end()) + { + object.second->get_statistics(statistics, visited, env, ns); + } + } +} diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 604a5f78688..45d3a5eae1c 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -43,6 +43,12 @@ class full_struct_abstract_objectt:public struct_abstract_objectt virtual abstract_object_pointert visit_sub_elements( const abstract_object_visitort &visitor) const override; + void get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const override; + private: // no entry means component is top typedef sharing_mapt diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index 5e4ab76749f..31ff0761d66 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -252,3 +252,17 @@ const constant_interval_exprt &interval_abstract_valuet::get_interval() const { return interval; } + +void interval_abstract_valuet::get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const +{ + abstract_valuet::get_statistics(statistics, visited, env, ns); + ++statistics.number_of_interval_abstract_objects; + if(interval.is_single_value_interval()) + { + ++statistics.number_of_single_value_intervals; + } +} diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h index f3ee3aa9890..7fe27989c1e 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.h +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -12,6 +12,7 @@ #include +#include "abstract_object_statistics.h" #include #include @@ -53,6 +54,12 @@ class interval_abstract_valuet:public abstract_valuet const constant_interval_exprt &get_interval() const; + void get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const override; + protected: CLONE virtual abstract_object_pointert merge( From 43f7e78f95ff6406a76e77c28b3566961cbfaf4b Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Fri, 6 Jul 2018 16:32:44 +0100 Subject: [PATCH 245/342] Add counts of various object types to environment statistics --- .../variable-sensitivity/abstract_enviroment.cpp | 12 ++++++++++++ .../abstract_object_statistics.h | 9 +++++++-- .../variable-sensitivity/array_abstract_object.cpp | 6 ++++++ .../variable-sensitivity/array_abstract_object.h | 3 +++ .../variable-sensitivity/constant_abstract_value.cpp | 9 +++++++++ .../variable-sensitivity/constant_abstract_value.h | 5 +++++ .../variable-sensitivity/pointer_abstract_object.cpp | 7 +++++++ .../variable-sensitivity/pointer_abstract_object.h | 3 +++ .../variable-sensitivity/struct_abstract_object.cpp | 6 ++++++ .../variable-sensitivity/struct_abstract_object.h | 3 +++ 10 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 8f1529353ef..4117c99189b 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 @@ -739,10 +740,21 @@ std::vector abstract_environmentt::modified_symbols( return symbols_diff; } +static std::size_t count_globals(const namespacet &ns) +{ + auto const& symtab = ns.get_symbol_table(); + auto val = std::count_if(symtab.begin(), symtab.end(), + [](const symbol_table_baset::const_iteratort::value_type& sym) { + return sym.second.is_lvalue && sym.second.is_static_lifetime; + }); + return val; +} + abstract_object_statisticst abstract_environmentt::gather_statistics(const namespacet &ns) const { abstract_object_statisticst statistics = {}; + statistics.number_of_globals = count_globals(ns); decltype(map)::viewt view; map.get_view(view); abstract_object_visitedt visited; diff --git a/src/analyses/variable-sensitivity/abstract_object_statistics.h b/src/analyses/variable-sensitivity/abstract_object_statistics.h index fbae4dee548..8a2d2c6d750 100644 --- a/src/analyses/variable-sensitivity/abstract_object_statistics.h +++ b/src/analyses/variable-sensitivity/abstract_object_statistics.h @@ -5,8 +5,13 @@ struct abstract_object_statisticst { - std::size_t number_of_interval_abstract_objects; - std::size_t number_of_single_value_intervals; + std::size_t number_of_interval_abstract_objects = 0; + std::size_t number_of_single_value_intervals = 0; + std::size_t number_of_structs = 0; + std::size_t number_of_arrays = 0; + std::size_t number_of_pointers = 0; + std::size_t number_of_constants = 0; + std::size_t number_of_globals = 0; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_STATISTICS_H diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index e8a3c7c4560..6b93144250a 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -199,3 +199,9 @@ sharing_ptrt array_abstract_objectt::write_index( new array_abstract_objectt(type(), true, false)); } } + +void array_abstract_objectt::get_statistics(abstract_object_statisticst &statistics, abstract_object_visitedt &visited, + const abstract_environmentt &env, const namespacet &ns) const { + abstract_objectt::get_statistics(statistics, visited, env, ns); + ++statistics.number_of_arrays; +} diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index aaeb6c885ed..281e397f650 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -39,6 +39,9 @@ class array_abstract_objectt:public abstract_objectt const abstract_object_pointert value, bool merging_write) const override; + void get_statistics(abstract_object_statisticst &statistics, abstract_object_visitedt &visited, + const abstract_environmentt &env, const namespacet &ns) const override; + protected: CLONE diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index 41986540d57..db5379f46d4 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -231,3 +231,12 @@ abstract_object_pointert constant_abstract_valuet::merge_constant_constant( } } } + +void constant_abstract_valuet::get_statistics(abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet& ns) const +{ + abstract_valuet::get_statistics(statistics, visited, env, ns); + ++statistics.number_of_constants; +} diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 082cc9e506a..fddc6843dd1 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -42,6 +42,11 @@ class constant_abstract_valuet:public abstract_valuet const class ai_baset &ai, const class namespacet &ns) const override; + void get_statistics(abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet& ns) const override; + protected: CLONE virtual abstract_object_pointert merge( diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index 6d569f8693d..9c0a7055a1b 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -191,3 +191,10 @@ sharing_ptrt new pointer_abstract_objectt(type(), true, false)); } } + +void +pointer_abstract_objectt::get_statistics(abstract_object_statisticst &statistics, abstract_object_visitedt &visited, + const abstract_environmentt &env, const namespacet &ns) const { + abstract_objectt::get_statistics(statistics, visited, env, ns); + ++statistics.number_of_pointers; +} diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index 935e7d54ac6..49388a3ace6 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -40,6 +40,9 @@ class pointer_abstract_objectt:public abstract_objectt const abstract_object_pointert value, bool merging_write) const override; + void get_statistics(abstract_object_statisticst &statistics, abstract_object_visitedt &visited, + const abstract_environmentt &env, const namespacet &ns) const override; + protected: CLONE diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index 7c2364b64af..bae43e84673 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -193,3 +193,9 @@ sharing_ptrt struct_abstract_objectt::write_component( new struct_abstract_objectt(type(), true, false)); } } + +void struct_abstract_objectt::get_statistics(abstract_object_statisticst &statistics, abstract_object_visitedt &visited, + const abstract_environmentt &env, const namespacet &ns) const { + abstract_objectt::get_statistics(statistics, visited, env, ns); + ++statistics.number_of_structs; +} diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index f3fdab164ad..255e7464fc3 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -38,6 +38,9 @@ class struct_abstract_objectt:public abstract_objectt const abstract_object_pointert value, bool merging_write) const override; + void get_statistics(abstract_object_statisticst &statistics, abstract_object_visitedt &visited, + const abstract_environmentt &env, const namespacet &ns) const override; + protected: CLONE From 04758e4af42ba39169f0eb8f112e9bf3682079c0 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Tue, 10 Jul 2018 13:53:02 +0100 Subject: [PATCH 246/342] Add an estimation of memory usage to object statistics This is an underestimation because it doesn't take into account memory allocated for ireps and some data structures (like the contexts for context_abstract_object) --- .../abstract_object_statistics.h | 3 +++ .../variable-sensitivity/constant_abstract_value.cpp | 1 + .../constant_array_abstract_object.cpp | 1 + .../constant_pointer_abstract_object.cpp | 1 + .../variable-sensitivity/context_abstract_object.cpp | 1 + .../full_struct_abstract_object.cpp | 1 + .../variable-sensitivity/interval_abstract_value.cpp | 1 + .../interval_array_abstract_object.cpp | 12 ++++++++++++ .../interval_array_abstract_object.h | 7 +++++++ 9 files changed, 28 insertions(+) diff --git a/src/analyses/variable-sensitivity/abstract_object_statistics.h b/src/analyses/variable-sensitivity/abstract_object_statistics.h index 8a2d2c6d750..a9dac9e653a 100644 --- a/src/analyses/variable-sensitivity/abstract_object_statistics.h +++ b/src/analyses/variable-sensitivity/abstract_object_statistics.h @@ -3,6 +3,7 @@ #include +#include struct abstract_object_statisticst { std::size_t number_of_interval_abstract_objects = 0; @@ -12,6 +13,8 @@ struct abstract_object_statisticst std::size_t number_of_pointers = 0; std::size_t number_of_constants = 0; std::size_t number_of_globals = 0; + /// An underestimation of the memory usage of the abstract objects + memory_sizet objects_memory_usage; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_STATISTICS_H diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index db5379f46d4..bdf1556e8b0 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -239,4 +239,5 @@ void constant_abstract_valuet::get_statistics(abstract_object_statisticst &stati { abstract_valuet::get_statistics(statistics, visited, env, ns); ++statistics.number_of_constants; + statistics.objects_memory_usage += memory_sizet::from_bytes(sizeof(*this)); } diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 4aa508d46b3..1c9d101acce 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -549,4 +549,5 @@ void constant_array_abstract_objectt::get_statistics( object.second->get_statistics(statistics, visited, env, ns); } } + statistics.objects_memory_usage += memory_sizet::from_bytes(sizeof(*this)); } diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 69513c7987f..c6a5077ed9c 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -373,4 +373,5 @@ void constant_pointer_abstract_objectt::get_statistics( { read_dereference(env, ns)->get_statistics(statistics, visited, env, ns); } + statistics.objects_memory_usage += memory_sizet::from_bytes(sizeof(*this)); } diff --git a/src/analyses/variable-sensitivity/context_abstract_object.cpp b/src/analyses/variable-sensitivity/context_abstract_object.cpp index 0eb0765209e..91ea958c352 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/context_abstract_object.cpp @@ -180,4 +180,5 @@ void context_abstract_objectt::get_statistics( { child_abstract_object->get_statistics(statistics, visited, env, ns); } + statistics.objects_memory_usage += memory_sizet::from_bytes(sizeof(*this)); } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 6a6599d0efe..c0a0764c2b9 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -496,4 +496,5 @@ void full_struct_abstract_objectt::get_statistics( object.second->get_statistics(statistics, visited, env, ns); } } + statistics.objects_memory_usage += memory_sizet::from_bytes(sizeof(*this)); } diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index 31ff0761d66..93b4a179521 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -265,4 +265,5 @@ void interval_abstract_valuet::get_statistics( { ++statistics.number_of_single_value_intervals; } + statistics.objects_memory_usage += memory_sizet::from_bytes(sizeof(*this)); } diff --git a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp index 340b11fb2c9..b3a7c010fb6 100644 --- a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp @@ -148,3 +148,15 @@ bool interval_array_abstract_objectt::eval_index( } return false; } + +void interval_array_abstract_objectt::get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const +{ + constant_array_abstract_objectt::get_statistics(statistics, visited, env, ns); + statistics.objects_memory_usage += memory_sizet::from_bytes( + // the size we add by inheriting + sizeof(*this) - sizeof(constant_array_abstract_objectt)); +} diff --git a/src/analyses/variable-sensitivity/interval_array_abstract_object.h b/src/analyses/variable-sensitivity/interval_array_abstract_object.h index 0b083fad8ac..b57d478046c 100644 --- a/src/analyses/variable-sensitivity/interval_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/interval_array_abstract_object.h @@ -43,6 +43,13 @@ class interval_array_abstract_objectt : public constant_array_abstract_objectt const abstract_environmentt &env, const namespacet &ns, mp_integer &out_index) const override; + +public: + void get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const override; }; #endif //PROJECT_INTERVAL_ARRAY_ABSTRACT_OBJECTT_H From aa2081b06a32b74945e7c73408ae1fc4db07a263 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 13 Jul 2018 15:07:29 +0100 Subject: [PATCH 247/342] Remove INVARIANT in full_struct_abstract_object copy constructor There are times during the process of writing to a struct that the copy constructor gets called (via mutable_clone) while the source object is in an 'in-flight' state which gets discarded by the time the full write actions have been completed. Leaving the INVARIANT check in-place causes some writes to fail because of the transiently inconsistent state of the full_struct_abstract_object. --- .../variable-sensitivity/full_struct_abstract_object.cpp | 4 +--- 1 file changed, 1 insertion(+), 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 c0a0764c2b9..688b6727805 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -28,9 +28,7 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com full_struct_abstract_objectt::full_struct_abstract_objectt( const full_struct_abstract_objectt &ao): struct_abstract_objectt(ao), map(ao.map) -{ - DATA_INVARIANT(verify(), "Structural invariants maintained"); -} +{ } /*******************************************************************\ From b66d8ef1cbad2fbcb8e425c2662d5c99ef70b2cc Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 13 Jul 2018 15:44:30 +0100 Subject: [PATCH 248/342] Make variable-sensitivity dependence graph produce control dependencies Previously the variable sensitivity domain dependence graph only produced data dependency information. This patch copies out the control dependency code from the original dependency graph code and patches those into the variable sensitivity dependence graph code. Note, this does *not* change the algorithm used to calculate the control dependencies, it just means we can calculate both control dependencies (using the original algorithm) and the data dependencies using the new variable sensitivity based algorithm in a single pass of the tools. --- .../variable_sensitivity_dependence_graph.cpp | 298 +++++++++++++++++- .../variable_sensitivity_dependence_graph.h | 171 +++++++++- 2 files changed, 459 insertions(+), 10 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index 1a0be8336be..262ad11a67b 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -22,7 +22,7 @@ * \param ns the namespace to use * \param deps the destination in which to accumlate data dependencies */ -void variable_sensitivity_dependence_grapht::eval_data_deps( +void variable_sensitivity_dependence_domaint::eval_data_deps( const exprt &expr, const namespacet &ns, data_depst &deps) const { const auto res= @@ -58,7 +58,7 @@ void variable_sensitivity_dependence_grapht::eval_data_deps( * \param ai the abstract interpreter * \param ns the namespace */ -void variable_sensitivity_dependence_grapht::transform( +void variable_sensitivity_dependence_domaint::transform( locationt from, locationt to, ai_baset &ai, @@ -66,6 +66,56 @@ void variable_sensitivity_dependence_grapht::transform( { variable_sensitivity_domaint::transform(from, to, ai, ns); + variable_sensitivity_dependence_grapht *dep_graph= + dynamic_cast(&ai); + assert(dep_graph!=nullptr); + + // propagate control dependencies across function calls + if(from->is_function_call()) + { + if(from->function == to->function) + { + control_dependencies(from, to, *dep_graph); + } + else + { + // edge to function entry point + const goto_programt::const_targett next = std::next(from); + + variable_sensitivity_dependence_domaint *s= + dynamic_cast + (&(dep_graph->get_state(next))); + assert(s!=nullptr); + + if(s->has_values.is_false()) + { + s->has_values=tvt::unknown(); + s->has_changed=true; + } + + // modify abstract state of return location + if(s->merge_control_dependencies( + control_deps, + control_dep_candidates)) + s->has_changed=true; + + control_deps.clear(); + control_dep_candidates.clear(); + } + } + else + control_dependencies(from, to, *dep_graph); + + // Find all the data dependencies in the the 'to' expression + data_dependencies(from, to, *dep_graph, ns); +} + +void variable_sensitivity_dependence_domaint::data_dependencies( + goto_programt::const_targett from, + goto_programt::const_targett to, + variable_sensitivity_dependence_grapht &dep_graph, + const namespacet &ns) +{ // Find all the data dependencies in the the 'to' expression domain_data_deps.clear(); if(to->is_assign()) @@ -76,6 +126,165 @@ void variable_sensitivity_dependence_grapht::transform( } } +void variable_sensitivity_dependence_domaint::control_dependencies( + goto_programt::const_targett from, + goto_programt::const_targett to, + variable_sensitivity_dependence_grapht &dep_graph) +{ + // Better Slicing of Programs with Jumps and Switches + // Kumar and Horwitz, FASE'02: + // "Node N is control dependent on node M iff N postdominates, in + // the CFG, one but not all of M's CFG successors." + // + // The "successor" above refers to an immediate successor of M. + + // Candidates for M for "to" are "from" and all existing control + // dependencies on nodes. "from" is added if it is a goto or assume + // instruction + + // Add new candidates + + if(from->is_goto() || from->is_assume()) + control_dep_candidates.insert(from); + else if(from->is_end_function()) + { + control_dep_candidates.clear(); + return; + } + + if(control_dep_candidates.empty()) + return; + + // Compute postdominators if needed + + const goto_functionst &goto_functions=dep_graph.goto_functions; + + const irep_idt id=goto_programt::get_function_id(from); + cfg_post_dominatorst &pd_tmp=dep_graph.cfg_post_dominators()[id]; + + goto_functionst::function_mapt::const_iterator f_it= + goto_functions.function_map.find(id); + + if(f_it==goto_functions.function_map.end()) + return; + + const goto_programt &goto_program=f_it->second.body; + + if(pd_tmp.cfg.size()==0) // have we computed the dominators already? + { + pd_tmp(goto_program); + } + + const cfg_post_dominatorst &pd=pd_tmp; + + // Check all candidates + + for(const auto &cd : control_dep_candidates) + { + // check all CFG successors of M + // special case: assumptions also introduce a control dependency + bool post_dom_all=!cd->is_assume(); + bool post_dom_one=false; + + // we could hard-code assume and goto handling here to improve + // performance + cfg_post_dominatorst::cfgt::entry_mapt::const_iterator e= + pd.cfg.entry_map.find(cd); + + assert(e!=pd.cfg.entry_map.end()); + + const cfg_post_dominatorst::cfgt::nodet &m= + pd.cfg[e->second]; + + // successors of M + for(const auto &edge : m.out) + { + const cfg_post_dominatorst::cfgt::nodet &m_s= + pd.cfg[edge.first]; + + if(m_s.dominators.find(to)!=m_s.dominators.end()) + post_dom_one=true; + else + post_dom_all=false; + } + + if(post_dom_all || !post_dom_one) + { + control_deps.erase(cd); + } + else + { + tvt branch=tvt::unknown(); + + if(cd->is_goto() && !cd->is_backwards_goto()) + { + goto_programt::const_targett t=cd->get_target(); + branch=to->location_number>=t->location_number?tvt(false):tvt(true); + } + + control_deps.insert(std::make_pair(cd, branch)); + } + } + + // add edges to the graph + for(const auto &c_dep : control_deps) + dep_graph.add_dep(vs_dep_edget::kindt::CTRL, c_dep.first, to); +} + +bool variable_sensitivity_dependence_domaint::merge_control_dependencies( + const control_depst &other_control_deps, + const control_dep_candidatest &other_control_dep_candidates) +{ + bool changed=false; + + // Merge control dependencies + + control_depst::iterator it=control_deps.begin(); + + for(const auto &c_dep : other_control_deps) + { + // find position to insert + while(it!=control_deps.end() && it->firstfirst) + { + // hint points at position that will follow the new element + control_deps.insert(it, c_dep); + changed=true; + } + else + { + assert(it!=control_deps.end()); + assert(!(it->firstfirst)); + + tvt &branch1=it->second; + const tvt &branch2=c_dep.second; + + if(branch1!=branch2 && !branch1.is_unknown()) + { + branch1=tvt::unknown(); + changed=true; + } + + ++it; + } + } + + // Merge control dependency candidates + + size_t n=control_dep_candidates.size(); + + control_dep_candidates.insert( + other_control_dep_candidates.begin(), + other_control_dep_candidates.end()); + + changed|=n!=control_dep_candidates.size(); + + return changed; +} + /** * Computes the join between "this" and "b" * @@ -84,7 +293,7 @@ void variable_sensitivity_dependence_grapht::transform( * \param to the current location * \return true if something has changed in the merge */ -bool variable_sensitivity_dependence_grapht::merge( +bool variable_sensitivity_dependence_domaint::merge( const variable_sensitivity_domaint &b, locationt from, locationt to) @@ -92,10 +301,13 @@ bool variable_sensitivity_dependence_grapht::merge( bool changed = false; changed = variable_sensitivity_domaint::merge(b, from, to); + changed |= has_values.is_false() || has_changed; - const auto cast_b = - dynamic_cast(b); + // Handle data dependencies + const auto& cast_b = + dynamic_cast(b); + // Merge data dependencies for (auto bdep : cast_b.domain_data_deps) { for(exprt bexpr : bdep.second) @@ -105,6 +317,13 @@ bool variable_sensitivity_dependence_grapht::merge( } } + changed |= merge_control_dependencies( + cast_b.control_deps, + cast_b.control_dep_candidates); + + has_changed=false; + has_values=tvt::unknown(); + return changed; } @@ -119,7 +338,7 @@ bool variable_sensitivity_dependence_grapht::merge( * between here and this will be retained. * \param ns: The global namespace */ -void variable_sensitivity_dependence_grapht::merge_three_way_function_return( +void variable_sensitivity_dependence_domaint::merge_three_way_function_return( const ai_domain_baset &function_call, const ai_domain_baset &function_start, const ai_domain_baset &function_end, @@ -144,11 +363,30 @@ void variable_sensitivity_dependence_grapht::merge_three_way_function_return( * \param ai the abstract domain * \param ns the namespace */ -void variable_sensitivity_dependence_grapht::output( +void variable_sensitivity_dependence_domaint::output( std::ostream &out, const ai_baset &ai, const namespacet &ns) const { + if(!control_deps.empty()) + { + out << "Control dependencies: "; + for(control_depst::const_iterator + it=control_deps.begin(); + it!=control_deps.end(); + ++it) + { + if(it!=control_deps.begin()) + out << ","; + + const goto_programt::const_targett cd=it->first; + const tvt branch=it->second; + + out << cd->location_number << " [" << branch << "]"; + } + out << "\n"; + } + if(!domain_data_deps.empty()) { out << "Data dependencies: "; @@ -185,12 +423,26 @@ void variable_sensitivity_dependence_grapht::output( * * \return the domain, formatted as a JSON object. */ -jsont variable_sensitivity_dependence_grapht::output_json( +jsont variable_sensitivity_dependence_domaint::output_json( const ai_baset &ai, const namespacet &ns) const { json_arrayt graph; + for(const auto &cd : control_deps) + { + const goto_programt::const_targett target=cd.first; + const tvt branch=cd.second; + + json_objectt &link=graph.push_back().make_object(); + + link["locationNumber"]= + json_numbert(std::to_string(target->location_number)); + link["sourceLocation"]=json(target->source_location); + link["type"]=json_stringt("control"); + link["branch"]=json_stringt(branch.to_string()); + } + for(const auto &dep : domain_data_deps) { json_objectt &link=graph.push_back().make_object(); @@ -213,3 +465,33 @@ jsont variable_sensitivity_dependence_grapht::output_json( return graph; } + +void variable_sensitivity_dependence_domaint::populate_dep_graph( + variable_sensitivity_dependence_grapht &dep_graph, + goto_programt::const_targett this_loc) const +{ + for(const auto &c_dep : control_deps) + dep_graph.add_dep(vs_dep_edget::kindt::CTRL, c_dep.first, this_loc); + + for(const auto &d_dep : domain_data_deps) + dep_graph.add_dep(vs_dep_edget::kindt::DATA, d_dep.first, this_loc); +} + +void variable_sensitivity_dependence_grapht::add_dep( + vs_dep_edget::kindt kind, + goto_programt::const_targett from, + goto_programt::const_targett to) +{ + const node_indext n_from=state_map[from].get_node_id(); + assert(n_from +#include + #include -class variable_sensitivity_dependence_grapht: +class variable_sensitivity_dependence_grapht; + +class vs_dep_edget +{ +public: + enum class kindt { NONE, CTRL, DATA, BOTH }; + + void add(kindt _kind) + { + switch(kind) + { + case kindt::NONE: + kind=_kind; + break; + case kindt::DATA: + case kindt::CTRL: + if(kind!=_kind) + kind=kindt::BOTH; + break; + case kindt::BOTH: + break; + } + } + + kindt get() const + { + return kind; + } + +protected: + kindt kind; +}; + +struct vs_dep_nodet:public graph_nodet +{ + typedef graph_nodet::edget edget; + typedef graph_nodet::edgest edgest; + + goto_programt::const_targett PC; +}; + +class variable_sensitivity_dependence_domaint: public variable_sensitivity_domaint { public: + typedef grapht::node_indext node_indext; + + explicit variable_sensitivity_dependence_domaint(): + node_id(std::numeric_limits::max()) + {} void transform( locationt from, @@ -44,7 +93,26 @@ class variable_sensitivity_dependence_grapht: const ai_baset &ai, const namespacet &ns) const override; + void populate_dep_graph( + variable_sensitivity_dependence_grapht &, + goto_programt::const_targett) const; + + void set_node_id(node_indext id) + { + node_id=id; + } + + node_indext get_node_id() const + { + assert(node_id!=std::numeric_limits::max()); + return node_id; + } + private: + node_indext node_id; + tvt has_values; + bool has_changed; + class dependency_ordert { public: @@ -55,11 +123,110 @@ class variable_sensitivity_dependence_grapht: return a->location_number < b->location_number; } }; - typedef std::map, dependency_ordert> data_depst; + typedef std::map< + goto_programt::const_targett, + std::set, dependency_ordert> data_depst; data_depst domain_data_deps; + typedef std::map control_depst; + control_depst control_deps; + + typedef std::set control_dep_candidatest; + control_dep_candidatest control_dep_candidates; + void eval_data_deps( const exprt &expr, const namespacet &ns, data_depst &deps) const; + + void control_dependencies( + goto_programt::const_targett from, + goto_programt::const_targett to, + variable_sensitivity_dependence_grapht &dep_graph); + + void data_dependencies( + goto_programt::const_targett from, + goto_programt::const_targett to, + variable_sensitivity_dependence_grapht &dep_graph, + const namespacet &ns); + + bool merge_control_dependencies( + const control_depst &other_control_deps, + const control_dep_candidatest &other_control_dep_candidates); +}; + +class variable_sensitivity_dependence_grapht: + public ait, + public grapht +{ +public: + using ait::operator[]; + using grapht::operator[]; + + friend class variable_sensitivity_dependence_domaint; + + typedef std::map post_dominators_mapt; + + explicit variable_sensitivity_dependence_grapht( + const goto_functionst &goto_functions, + const namespacet &_ns, + const bool print_progress = false, + const float min_progress_interval = 0): + ait(print_progress, min_progress_interval), + goto_functions(goto_functions), + ns(_ns) + { + } + + void initialize(const goto_functionst &goto_functions) + { + ait::initialize(goto_functions); + } + + void initialize(const goto_programt &goto_program) + { + ait::initialize(goto_program); + } + + void finalize() + { + for(const auto &location_state : state_map) + { + location_state.second.populate_dep_graph(*this, location_state.first); + } + } + + + + void add_dep( + vs_dep_edget::kindt kind, + goto_programt::const_targett from, + goto_programt::const_targett to); + + virtual statet &get_state(goto_programt::const_targett l) + { + std::pair entry= + state_map.insert( + std::make_pair(l, variable_sensitivity_dependence_domaint())); + + if(entry.second) + { + const node_indext node_id=add_node(); + entry.first->second.set_node_id(node_id); + nodes[node_id].PC=l; + } + + return entry.first->second; + } + + post_dominators_mapt &cfg_post_dominators() + { + return post_dominators; + } + +protected: + const goto_functionst &goto_functions; + const namespacet &ns; + + post_dominators_mapt post_dominators; }; // NOLINTNEXTLINE(whitespace/line_length) From a88eac1a9a25b8d43bba959918f0d2d5b449b8f1 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 13 Jul 2018 15:11:23 +0100 Subject: [PATCH 249/342] Add support for bit field and enums intervals.cpp --- .../main.c | 14 ++++++++++++++ .../test.desc | 8 ++++++++ 2 files changed, 22 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-bit-field-intervals/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/main.c b/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/main.c new file mode 100644 index 00000000000..013100b8895 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/main.c @@ -0,0 +1,14 @@ +struct bitfield_struct { + unsigned char byte; + unsigned char bitfield:1; +}; + +extern struct bitfield_struct bs; + +void main(void) +{ + bs.byte = 10; + bs.bitfield = 1; + __CPROVER_assert(bs.byte==10, "bs.byte==10"); + __CPROVER_assert(bs.bitfield==1, "bs.bitfield==1"); +} diff --git a/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc b/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc new file mode 100644 index 00000000000..402ca88b869 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--function main --variable --structs --interval-values --verify +^EXIT=0$ +^SIGNAL=0$ +\[main\.assertion\.1\] .* bs\.byte==10: Success +\[main\.assertion\.2\] .* bs\.bitfield==1: Success +-- From c9a6b536014b54742b74c5099804e453a9772185 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 13 Jul 2018 15:47:21 +0100 Subject: [PATCH 250/342] Avoid creating interval_abstract_valuet's for float types Currently interval_abstract_valuet only supports integral types, but the object factory was attempting to create them for float types anyway. This patch ensures that for float types we fall back to creating constant_abstract_valuet instead. --- .../variable_sensitivity_object_factory.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 88ba88f7e21..36176b06aad 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -32,12 +32,16 @@ variable_sensitivity_object_factoryt::ABSTRACT_OBJECT_TYPET 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_fixedbv || type.id()==ID_c_bool || type.id()==ID_bool || type.id()==ID_integer || type.id()==ID_c_bit_field) { abstract_object_type=has_interval?INTERVAL:CONSTANT; } + else if(type.id()==ID_floatbv) + { + abstract_object_type=CONSTANT; + } else if(type.id()==ID_array) { abstract_object_type=has_arrays_flag?ARRAY_SENSITIVE:ARRAY_INSENSITIVE; From 29ecc3e463cc60688fe40587b33f4c19ebfd4dde Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 13 Jul 2018 15:51:57 +0100 Subject: [PATCH 251/342] Add a basic implementation of to_constant for interval_abstract_valuet --- .../variable-sensitivity/interval_abstract_value.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index 93b4a179521..ada82d5974a 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -59,6 +59,12 @@ interval_abstract_valuet::interval_abstract_valuet( exprt interval_abstract_valuet::to_constant() const { + // Attempt to reduce this interval to a constant expression + if(interval.is_single_value_interval()) + { + // Interval is the equivalent of a constant, so reduce it to a constant + return to_constant_expr(interval.get_lower()); + } return abstract_objectt::to_constant(); #if 0 if(!is_top() && !is_bottom()) From 43352078b2a8f7efb472de499c5ef999ecd1b38a Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 13 Jul 2018 15:55:50 +0100 Subject: [PATCH 252/342] Crude ability to expression_transform mixed interval and non-intervals --- .../interval_abstract_value.cpp | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index ada82d5974a..189bb685ca0 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -92,8 +92,28 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( for(const auto &op : operands) { - const auto iav + auto iav = std::dynamic_pointer_cast(op); + if (!iav) + { + // The operand isn't an interval - if it's an integral constant we can + // convert it into an interval. + + if(constant_interval_exprt::is_int(op->type())) + { + const auto ivop = environment.abstract_object_factory(op->type(), op->to_constant(), ns); + iav = std::dynamic_pointer_cast(ivop); + } + + if(!iav) + { + // If we could not convert the operand into an interval, + // e.g. if its type is not something we can represent as an interval, + // try dispatching the expression_transform under that type instead. + return op->expression_transform(expr, operands, environment, ns); + } + } + INVARIANT(iav, "Should be an interval abstract value"); interval_operands.push_back(iav); } From d05701ce81a697dbda0143659a782c340ab112a9 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 13 Jul 2018 16:01:41 +0100 Subject: [PATCH 253/342] Added regression test for variable sensitivity intervals with mixed float/bool expressions --- .../main.c | 18 ++++++++++++++++++ .../test.desc | 8 ++++++++ 2 files changed, 26 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/main.c new file mode 100644 index 00000000000..52e7476f814 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/main.c @@ -0,0 +1,18 @@ +void main(int argc, char *argv[]) +{ + float x = 2.5; + float y = 1.5; + int z = 0; + + if(x > y) + z = 1; + + __CPROVER_assert(z == 1, "x > y, z == 1"); + + y = 2.6; + + if(x > y) + z = 3; + + __CPROVER_assert(z == 1, "x < y, z == 1"); +} diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/test.desc new file mode 100644 index 00000000000..6c1444dd97e --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--variable-sensitivity --interval-values --verify +\[main.assertion.*\] .* function main, x > y, z == 1: Success +\[main.assertion.*\] .* function main, x < y, z == 1: Success +^EXIT=0$ +^SIGNAL=0$ +-- From be0d9a730722c4a756707f6df7fbc74c5dbeeb3c Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 13 Jul 2018 16:08:12 +0100 Subject: [PATCH 254/342] Include function call arguments in variable sensitivity dependency graph --- .../variable_sensitivity_dependence_graph.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index 262ad11a67b..f4bae68a072 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -124,6 +124,15 @@ void variable_sensitivity_dependence_domaint::data_dependencies( eval_data_deps(inst.rhs(), ns, domain_data_deps); } + else if (to->is_function_call()) + { + const code_function_callt &call = to_code_function_call(to->code); + const code_function_callt::argumentst &args= call.arguments(); + for(const auto arg : args) + { + eval_data_deps(arg, ns, domain_data_deps); + } + } } void variable_sensitivity_dependence_domaint::control_dependencies( From 6bd5bfd67725d6189d988b9725600e425b69af77 Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 20:00:55 +0000 Subject: [PATCH 255/342] Move ai configuration to separate config object This lets us reuse the logic of getting the ait configuration from command line options. Also, this includes a small simplification of the printing logic --- .../variable_sensitivity_dependence_graph.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h index 5a86746d2d6..85746643af7 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -168,9 +168,8 @@ class variable_sensitivity_dependence_grapht: explicit variable_sensitivity_dependence_grapht( const goto_functionst &goto_functions, const namespacet &_ns, - const bool print_progress = false, - const float min_progress_interval = 0): - ait(print_progress, min_progress_interval), + const ai_configt &config = {}) + : ait(config), goto_functions(goto_functions), ns(_ns) { From 6fe0f9c2add66e22ddcb1e95270ed8885cb44e38 Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 20:01:33 +0000 Subject: [PATCH 256/342] Add option to print statistics about the VS domain --- .../variable_sensitivity_domain.cpp | 5 +++ .../variable_sensitivity_domain.h | 43 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 81378c46ee6..70419b5f00e 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -592,3 +592,8 @@ void variable_sensitivity_domaint::apply_domain( abstract_state.assign(symbol, value, ns); } } +abstract_object_statisticst +variable_sensitivity_domaint::gather_statistics(const namespacet &ns) const +{ + return abstract_state.gather_statistics(ns); +} diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 9a755869b9b..17058b6ef6d 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -137,6 +137,49 @@ class variable_sensitivity_domaint:public ai_domain_baset const namespacet &ns); abstract_environmentt abstract_state; + +public: + abstract_object_statisticst gather_statistics(const namespacet &ns) const; +}; + +template <> +struct get_domain_statisticst +{ + abstract_object_statisticst total_statistics = {}; + void + add_entry(const variable_sensitivity_domaint &domain, const namespacet &ns) + { + auto statistics = domain.gather_statistics(ns); + total_statistics.number_of_interval_abstract_objects += + statistics.number_of_interval_abstract_objects; + total_statistics.number_of_globals += statistics.number_of_globals; + total_statistics.number_of_single_value_intervals += + statistics.number_of_single_value_intervals; + total_statistics.number_of_constants += statistics.number_of_constants; + total_statistics.number_of_pointers += statistics.number_of_constants; + total_statistics.number_of_arrays += statistics.number_of_arrays; + total_statistics.number_of_structs += statistics.number_of_arrays; + total_statistics.objects_memory_usage += statistics.objects_memory_usage; + } + + void print(std::ostream &out) const + { + out << "<< Begin Variable Sensitivity Domain Statistics >>\n" + << " Memory Usage: " + << total_statistics.objects_memory_usage.to_string() << '\n' + << " Number of structs: " << total_statistics.number_of_structs << '\n' + << " Number of arrays: " << total_statistics.number_of_arrays << '\n' + << " Number of pointers: " << total_statistics.number_of_pointers + << '\n' + << " Number of constants: " << total_statistics.number_of_constants + << '\n' + << " Number of intervals: " + << total_statistics.number_of_interval_abstract_objects << '\n' + << " Number of single value intervals: " + << total_statistics.number_of_single_value_intervals << '\n' + << " Number of globals: " << total_statistics.number_of_globals << '\n' + << "<< End Variable Sensitivity Domain Statistics >>\n"; + } }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H From 34aa619185c131ea407799de652185796de392b8 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Fri, 20 Jul 2018 15:54:04 +0100 Subject: [PATCH 257/342] Disable currently broken dependence graph tests --- regression/goto-analyzer/dependence-graph10/test.desc | 2 +- regression/goto-analyzer/dependence-graph11/test.desc | 2 +- regression/goto-analyzer/dependence-graph12/test.desc | 2 +- regression/goto-analyzer/dependence-graph4/test.desc | 2 +- regression/goto-analyzer/dependence-graph7/test.desc | 2 +- regression/goto-analyzer/dependence-graph8/test.desc | 2 +- regression/goto-analyzer/dependence-graph9/test.desc | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/regression/goto-analyzer/dependence-graph10/test.desc b/regression/goto-analyzer/dependence-graph10/test.desc index 26943fc2e68..42ae3800a9b 100644 --- a/regression/goto-analyzer/dependence-graph10/test.desc +++ b/regression/goto-analyzer/dependence-graph10/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --dependence-graph --show activate-multi-line-match diff --git a/regression/goto-analyzer/dependence-graph11/test.desc b/regression/goto-analyzer/dependence-graph11/test.desc index 32969498ac0..d316a2e3f0d 100644 --- a/regression/goto-analyzer/dependence-graph11/test.desc +++ b/regression/goto-analyzer/dependence-graph11/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --dependence-graph --show activate-multi-line-match diff --git a/regression/goto-analyzer/dependence-graph12/test.desc b/regression/goto-analyzer/dependence-graph12/test.desc index 419f4efc4e1..6bd22947426 100644 --- a/regression/goto-analyzer/dependence-graph12/test.desc +++ b/regression/goto-analyzer/dependence-graph12/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --dependence-graph --show activate-multi-line-match diff --git a/regression/goto-analyzer/dependence-graph4/test.desc b/regression/goto-analyzer/dependence-graph4/test.desc index 670220ddf98..16a2d8905cc 100644 --- a/regression/goto-analyzer/dependence-graph4/test.desc +++ b/regression/goto-analyzer/dependence-graph4/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --show --dependence-graph --text - activate-multi-line-match diff --git a/regression/goto-analyzer/dependence-graph7/test.desc b/regression/goto-analyzer/dependence-graph7/test.desc index 80a11db5a17..516c149ddaa 100644 --- a/regression/goto-analyzer/dependence-graph7/test.desc +++ b/regression/goto-analyzer/dependence-graph7/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --dependence-graph --show activate-multi-line-match diff --git a/regression/goto-analyzer/dependence-graph8/test.desc b/regression/goto-analyzer/dependence-graph8/test.desc index 50a092d6d9e..7a62b6868c7 100644 --- a/regression/goto-analyzer/dependence-graph8/test.desc +++ b/regression/goto-analyzer/dependence-graph8/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --dependence-graph --show activate-multi-line-match diff --git a/regression/goto-analyzer/dependence-graph9/test.desc b/regression/goto-analyzer/dependence-graph9/test.desc index c6dd50d71cb..ca075f63118 100644 --- a/regression/goto-analyzer/dependence-graph9/test.desc +++ b/regression/goto-analyzer/dependence-graph9/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --dependence-graph --show activate-multi-line-match From bab158a76f374a8d677e3c435c39fa2232f2699b Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Mon, 23 Jul 2018 17:48:27 +0100 Subject: [PATCH 258/342] Disable interval float test --- .../variable-sensitivity-interval-values-float/test.desc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-float/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-float/test.desc index 7dd2b52d752..0fa2d53d8d6 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-float/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-float/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --variable-sensitivity --interval-values --show main::1::zero \(\) -> \[00000000000000000000000000000000, 00000000000000000000000000000000\] @@ -8,4 +8,4 @@ main::1::between_minus_one_and_one \(\) -> \[10111111100000000000000000000000, 0 main::1::thirteen \(\) -> \[01000001010100000000000000000000, 01000001010100000000000000000000\] ^EXIT=0$ ^SIGNAL=0$ --- \ No newline at end of file +-- From 50a135e01aacddf7a6d68daabb854b267f23ace7 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Tue, 24 Jul 2018 14:46:12 +0100 Subject: [PATCH 259/342] Fix variable sensitivity unit test --- unit/analyses/variable-sensitivity/last_written_location.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/unit/analyses/variable-sensitivity/last_written_location.cpp b/unit/analyses/variable-sensitivity/last_written_location.cpp index 3fba8c16c57..87dc6e87c88 100644 --- a/unit/analyses/variable-sensitivity/last_written_location.cpp +++ b/unit/analyses/variable-sensitivity/last_written_location.cpp @@ -24,6 +24,7 @@ #include #include #include +#include //#include @@ -50,6 +51,8 @@ SCENARIO("Constructing two environments to make sure we correctly identify modif symbol_table.add(second_sym); namespacet ns(symbol_table); + variable_sensitivity_object_factoryt::instance().set_options(optionst{}); + WHEN("The identifiers get inserted into two environments") { abstract_environmentt env; From cb759f7378df44c210679f7a2ee0cb37103e8816 Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 20:02:33 +0000 Subject: [PATCH 260/342] Apply bandaid fix to variable sensitivity The C++ standard leaves comparing iterators from different containers against each other as undefined behaviour. We've been doing this with goto locations, which let us run into standard library assertion failures during testing in debug builds. This "fixes" this by avoiding the usage of the standard comparison operators for iterators in places that led to regression test failures. Going forward, we should probably consider representing goto locations in a less brittle manner, or at least provide a wrapper with sane comparison semantics for the list iterators we're currently using. --- .../variable-sensitivity/data_dependency_context.cpp | 9 ++++++--- .../variable-sensitivity/variable_sensitivity_domain.cpp | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/analyses/variable-sensitivity/data_dependency_context.cpp b/src/analyses/variable-sensitivity/data_dependency_context.cpp index f7f0ad439c7..f820d67a4f7 100644 --- a/src/analyses/variable-sensitivity/data_dependency_context.cpp +++ b/src/analyses/variable-sensitivity/data_dependency_context.cpp @@ -97,9 +97,12 @@ abstract_object_pointert data_dependency_contextt::insert_data_deps( else { std::set_difference( - dependencies.begin(), dependencies.end(), - data_deps.begin(), data_deps.end(), - std::inserter(new_dependencies, new_dependencies.begin())); + dependencies.begin(), + dependencies.end(), + data_deps.begin(), + data_deps.end(), + std::inserter(new_dependencies, new_dependencies.begin()), + location_ordert{}); } // If there are no new dependencies to add, just return diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 70419b5f00e..5048d00439d 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -412,7 +412,7 @@ void variable_sensitivity_domaint::transform_function_call( const code_function_callt::argumentst &called_arguments= function_call.arguments(); - if(to==next) + if(is_same_code_location(to, next)) { if(ignore_function_call_transform(function_id)) { From fbcd383e2ba0a71ddd409d9121523f49bab47657 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Thu, 26 Jul 2018 17:38:21 +0100 Subject: [PATCH 261/342] Add control dependencies from function call to function entry point for new dependency graph --- .../main.c | 9 ++++++++ .../test.desc | 12 +++++++++++ .../variable_sensitivity_dependence_graph.cpp | 21 +++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph-01/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph-01/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-01/main.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph-01/main.c new file mode 100644 index 00000000000..952647449fb --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-01/main.c @@ -0,0 +1,9 @@ +void func() +{ + +} + +void main(void) +{ + func(); +} diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-01/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-01/test.desc new file mode 100644 index 00000000000..9d9f776c343 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-01/test.desc @@ -0,0 +1,12 @@ +CORE +main.c +--show --dependence-graph-vs +activate-multi-line-match +^EXIT=0$ +^SIGNAL=0$ +Function: main\n.*\n.*\n.*\nControl dependencies: [0-9]+ +Function: func\n.*\n.*\n.*\nControl dependencies: [0-9]+ +Function: __CPROVER_initialize\n.*\n.*\n.*\nControl dependencies: [0-9]+ +-- +Function: __CPROVER__start\n.*\n.*\n.*\nControl dependencies: [0-9]+ +^warning: ignoring diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index f4bae68a072..005f8e627bc 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -70,6 +70,25 @@ void variable_sensitivity_dependence_domaint::transform( dynamic_cast(&ai); assert(dep_graph!=nullptr); + // We do not propagate control dependencies on function calls, i.e., only the + // entry point of a function should have a control dependency on the call + if(!control_deps.empty()) + { + const goto_programt::const_targett &dep = control_deps.begin()->first; + if(dep->is_function_call()) + { + INVARIANT( + std::all_of( + std::next(control_deps.begin()), + control_deps.end(), + [](const std::pair &d) + { return d.first->is_function_call(); }), + "All entries must be function calls"); + + control_deps.clear(); + } + } + // propagate control dependencies across function calls if(from->is_function_call()) { @@ -100,6 +119,8 @@ void variable_sensitivity_dependence_domaint::transform( s->has_changed=true; control_deps.clear(); + control_deps.insert(std::make_pair(from, tvt::unknown())); + control_dep_candidates.clear(); } } From 010c0d8a8b698564352fd5f669b009001ad430f5 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 27 Jul 2018 17:31:45 +0100 Subject: [PATCH 262/342] Fix write_stack to correctly complete types for index_exprt expressions --- .../goto-analyzer/write-stack-types/test.desc | 8 +++++ .../write-stack-address-of.c | 34 +++++++++++++++++++ .../variable-sensitivity/write_stack.cpp | 3 ++ .../write_stack_entry.cpp | 24 +++++++++++-- .../variable-sensitivity/write_stack_entry.h | 3 ++ 5 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 regression/goto-analyzer/write-stack-types/test.desc create mode 100644 regression/goto-analyzer/write-stack-types/write-stack-address-of.c diff --git a/regression/goto-analyzer/write-stack-types/test.desc b/regression/goto-analyzer/write-stack-types/test.desc new file mode 100644 index 00000000000..6645d1f5645 --- /dev/null +++ b/regression/goto-analyzer/write-stack-types/test.desc @@ -0,0 +1,8 @@ +CORE +write-stack-address-of.c +--variable --structs --pointers --verify +^EXIT=0$ +^SIGNAL=0$ +^\[func1.assertion.1\] .* func1.a == 0: Unknown$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/write-stack-types/write-stack-address-of.c b/regression/goto-analyzer/write-stack-types/write-stack-address-of.c new file mode 100644 index 00000000000..f4b4649edd0 --- /dev/null +++ b/regression/goto-analyzer/write-stack-types/write-stack-address-of.c @@ -0,0 +1,34 @@ +typedef unsigned short uint16; + +struct st { + uint16 data1; +} str1; + +extern struct { + struct st data2; +} g_sts; + +void func1(uint16 a) +{ + // Expect the assert to be 'Unknown' because we would expect 'a' to be TOP + // here because p->data1 passed in as argument should be TOP. + __CPROVER_assert(a == 0, "func1.a == 0"); +} + +void func2(struct st *p) +{ + func1(p->data1); +} + +void main(void) +{ + const int s_map_data[] = { 2, 10, 20, 100, 110 }; + + int *p_map_x = &s_map_data[1]; + int *p_map_y = p_map_x + 1 ; + + // Tests that the write_stack handles &smap_data[1] + __CPROVER_assert(*p_map_y == 20, "*main.p_map_y == 20"); + + func2(&g_sts.data2); +} diff --git a/src/analyses/variable-sensitivity/write_stack.cpp b/src/analyses/variable-sensitivity/write_stack.cpp index 54c89b38115..5183ba9da8f 100644 --- a/src/analyses/variable-sensitivity/write_stack.cpp +++ b/src/analyses/variable-sensitivity/write_stack.cpp @@ -188,6 +188,9 @@ exprt write_stackt::to_expression() const } new_expr.op0()=access_expr; + // If neccesary, complete the type of the new access expression + entry->adjust_access_type(new_expr); + access_expr=new_expr; } } diff --git a/src/analyses/variable-sensitivity/write_stack_entry.cpp b/src/analyses/variable-sensitivity/write_stack_entry.cpp index 73731e7519d..0523522a1eb 100644 --- a/src/analyses/variable-sensitivity/write_stack_entry.cpp +++ b/src/analyses/variable-sensitivity/write_stack_entry.cpp @@ -35,6 +35,11 @@ exprt simple_entryt::get_access_expr() const return simple_entry; } +/// For a simple entry, no type adjustment is needed for the access expression +void simple_entryt::adjust_access_type(exprt &expr) const +{ +} + offset_entryt::offset_entryt(abstract_object_pointert offset_value): offset(offset_value) { @@ -46,13 +51,28 @@ offset_entryt::offset_entryt(abstract_object_pointert offset_value): } /// Get the expression part needed to read this stack entry. For offset entries -/// this is an index expression with the index() part the offset -/// \return The expression to read this part of the stack +/// this is an index expression with the index() part the offset. +/// It is important to note that the returned index_exprt does not have a type, +/// so it will be necessary for the caller to update the type whenever the index +/// expression is completed using `adjust_access_type` on the resulting exprt. +/// \return The untyped expression to read this part of the stack exprt offset_entryt::get_access_expr() const { + // This constructs a something that is basicallyt '(null)[offset])' + // meaning that we don't know what the type is at this point, as the + // array part will be filled in later. return index_exprt(exprt(), offset->to_constant()); } +/// For an offset entry, the type of the access expression can only be +/// determined once the access expression has been completed with the next +/// entry on the write stack. +void offset_entryt::adjust_access_type(exprt &expr) const +{ + PRECONDITION(expr.id() == ID_index); + expr.type()=expr.op0().type().subtype(); +} + /// Try to combine a new stack element with the current top of the stack. This /// will succeed if they are both offsets as we can combine these offsets into /// the sum of the offsets diff --git a/src/analyses/variable-sensitivity/write_stack_entry.h b/src/analyses/variable-sensitivity/write_stack_entry.h index 5f35ed15311..60b4e6c046d 100644 --- a/src/analyses/variable-sensitivity/write_stack_entry.h +++ b/src/analyses/variable-sensitivity/write_stack_entry.h @@ -25,6 +25,7 @@ class write_stack_entryt public: virtual ~write_stack_entryt() = default; virtual exprt get_access_expr() const=0; + virtual void adjust_access_type(exprt &expr) const = 0; virtual bool try_squash_in( std::shared_ptr new_entry, const abstract_environmentt &enviroment, @@ -36,6 +37,7 @@ class simple_entryt:public write_stack_entryt public: explicit simple_entryt(exprt expr); virtual exprt get_access_expr() const override; + virtual void adjust_access_type(exprt &expr) const override; private: exprt simple_entry; }; @@ -45,6 +47,7 @@ class offset_entryt:public write_stack_entryt public: explicit offset_entryt(abstract_object_pointert offset_value); virtual exprt get_access_expr() const override; + virtual void adjust_access_type(exprt &expr) const override; virtual bool try_squash_in( std::shared_ptr new_entry, const abstract_environmentt &enviroment, From 55811b99e2f9b5ef4e7e2b54fc5fd31f7dcf422d Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 27 Jul 2018 17:58:01 +0100 Subject: [PATCH 263/342] Avoid breaking fixpoint when merging data_dependency_context When merging two data_dependency_context abstract objects, ensure a new abstract object is returned iff the dependencies have actually been updated. Previously a new result object was getting unconditionally returned, even if its data did not change. This was causing fixpoint to fail to terminate. --- .../main.c | 21 +++++++++++++++++++ .../test.desc | 7 +++++++ .../data_dependency_context.cpp | 8 ++++++- 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/main.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/main.c new file mode 100644 index 00000000000..2d27861bce5 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/main.c @@ -0,0 +1,21 @@ +void cal(void) +{ + +} + +const int g_N = 5; +int x = 0; + +struct { + int idx; +} s_str = { 0 }; + +void main(void) +{ + for (int i = 0; i < g_N; i++) { + cal(); + s_str.idx = s_str.idx + 1; + } + + __CPROVER_assert(s_str.idx > 1, "s_str.idx > 1"); +} diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc new file mode 100644 index 00000000000..19db1df596d --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc @@ -0,0 +1,7 @@ +CORE +main.c +--dependence-graph-vs --structs --arrays --verify +EXIT=0 +SIGNAL=0 +^\[main.assertion.1\] file .* function main, idx==1: Unknown$ +-- diff --git a/src/analyses/variable-sensitivity/data_dependency_context.cpp b/src/analyses/variable-sensitivity/data_dependency_context.cpp index f820d67a4f7..3c326d67810 100644 --- a/src/analyses/variable-sensitivity/data_dependency_context.cpp +++ b/src/analyses/variable-sensitivity/data_dependency_context.cpp @@ -228,7 +228,13 @@ abstract_object_pointert data_dependency_contextt::merge( std::inserter(result->data_dominators, result->data_dominators.end()), location_ordert()); - return result; + // It is critically important that we only return a newly constructed result + // abstract object *iff* the data has actually changed, otherwise AI may + // never reach a fixpoint + if(has_been_modified(result)) + return result; + else + return shared_from_this(); } return abstract_objectt::merge(other); From 091943faf9127ac89d1e0f0aba4385c7b6fbeb38 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Tue, 31 Jul 2018 17:03:57 +0100 Subject: [PATCH 264/342] Add specialised ai domain methods for variable sensitivity dependence graph --- .../variable_sensitivity_dependence_graph.h | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h index 85746643af7..66d0fbb892d 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -63,7 +63,9 @@ class variable_sensitivity_dependence_domaint: typedef grapht::node_indext node_indext; explicit variable_sensitivity_dependence_domaint(): - node_id(std::numeric_limits::max()) + node_id(std::numeric_limits::max()), + has_values(false), + has_changed(false) {} void transform( @@ -72,6 +74,41 @@ class variable_sensitivity_dependence_domaint: ai_baset &ai, const namespacet &ns) override; + virtual void make_bottom() override + { + variable_sensitivity_domaint::make_bottom(); + has_values = tvt(false); + has_changed = false; + domain_data_deps.clear(); + control_deps.clear(); + control_dep_candidates.clear(); + } + + virtual void make_top() override + { + variable_sensitivity_domaint::make_top(); + has_values = tvt(true); + has_changed = false; + domain_data_deps.clear(); + control_deps.clear(); + control_dep_candidates.clear(); + } + + virtual void make_entry() override + { + make_top(); + } + + bool is_bottom() const override + { + return variable_sensitivity_domaint::is_bottom() && has_values.is_false(); + } + + bool is_top() const override + { + return variable_sensitivity_domaint::is_top() && has_values.is_true(); + } + virtual bool merge( const variable_sensitivity_domaint &b, locationt from, From 64ec7fd8180c2f45cc2ac8d3f244e040ee2acae7 Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Wed, 1 Aug 2018 14:05:59 +0100 Subject: [PATCH 265/342] Control dependencies of function body instructions to function calls for variable sensitivity dependence graph --- .../main.c | 11 +++ .../test.desc | 11 +++ .../variable_sensitivity_dependence_graph.cpp | 73 ++++++++++++------- .../variable_sensitivity_dependence_graph.h | 8 +- 4 files changed, 77 insertions(+), 26 deletions(-) create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph-02/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph-02/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-02/main.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph-02/main.c new file mode 100644 index 00000000000..33eb267e9d1 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-02/main.c @@ -0,0 +1,11 @@ +void main(void) +{ + int a; + + if(a) + { + a = 1; + } + + a = 2; +} diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-02/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-02/test.desc new file mode 100644 index 00000000000..4971c164466 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-02/test.desc @@ -0,0 +1,11 @@ +CORE +main.c +--show --dependence-graph-vs +activate-multi-line-match +^EXIT=0$ +^SIGNAL=0$ +Control dependencies: [0-9]+ \[TRUE\]\n.*\n.*\n\s+a = 1; +Control dependencies: [0-9]+ \[UNCONDITIONAL\]\n.*\n.*\n\s+a = 2; + +-- +^warning: ignoring diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index 005f8e627bc..77116596dd2 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -70,25 +70,6 @@ void variable_sensitivity_dependence_domaint::transform( dynamic_cast(&ai); assert(dep_graph!=nullptr); - // We do not propagate control dependencies on function calls, i.e., only the - // entry point of a function should have a control dependency on the call - if(!control_deps.empty()) - { - const goto_programt::const_targett &dep = control_deps.begin()->first; - if(dep->is_function_call()) - { - INVARIANT( - std::all_of( - std::next(control_deps.begin()), - control_deps.end(), - [](const std::pair &d) - { return d.first->is_function_call(); }), - "All entries must be function calls"); - - control_deps.clear(); - } - } - // propagate control dependencies across function calls if(from->is_function_call()) { @@ -115,13 +96,15 @@ void variable_sensitivity_dependence_domaint::transform( // modify abstract state of return location if(s->merge_control_dependencies( control_deps, - control_dep_candidates)) + control_dep_candidates, + control_dep_calls)) s->has_changed=true; control_deps.clear(); - control_deps.insert(std::make_pair(from, tvt::unknown())); - control_dep_candidates.clear(); + + control_dep_calls.clear(); + control_dep_calls.insert(from); } } else @@ -178,7 +161,9 @@ void variable_sensitivity_dependence_domaint::control_dependencies( control_dep_candidates.insert(from); else if(from->is_end_function()) { + control_deps.clear(); control_dep_candidates.clear(); + control_dep_calls.clear(); return; } @@ -253,6 +238,7 @@ void variable_sensitivity_dependence_domaint::control_dependencies( } control_deps.insert(std::make_pair(cd, branch)); + control_dep_calls.clear(); } } @@ -263,7 +249,8 @@ void variable_sensitivity_dependence_domaint::control_dependencies( bool variable_sensitivity_dependence_domaint::merge_control_dependencies( const control_depst &other_control_deps, - const control_dep_candidatest &other_control_dep_candidates) + const control_dep_candidatest &other_control_dep_candidates, + const control_dep_callst &other_control_dep_calls) { bool changed=false; @@ -312,6 +299,16 @@ bool variable_sensitivity_dependence_domaint::merge_control_dependencies( changed|=n!=control_dep_candidates.size(); + // Merge call control dependencies + + n=control_dep_calls.size(); + + control_dep_calls.insert( + other_control_dep_calls.begin(), + other_control_dep_calls.end()); + + changed|=n!=control_dep_calls.size(); + return changed; } @@ -349,7 +346,8 @@ bool variable_sensitivity_dependence_domaint::merge( changed |= merge_control_dependencies( cast_b.control_deps, - cast_b.control_dep_candidates); + cast_b.control_dep_candidates, + cast_b.control_dep_calls); has_changed=false; has_values=tvt::unknown(); @@ -398,7 +396,7 @@ void variable_sensitivity_dependence_domaint::output( const ai_baset &ai, const namespacet &ns) const { - if(!control_deps.empty()) + if(!control_deps.empty() || !control_dep_calls.empty()) { out << "Control dependencies: "; for(control_depst::const_iterator @@ -414,6 +412,18 @@ void variable_sensitivity_dependence_domaint::output( out << cd->location_number << " [" << branch << "]"; } + + for(control_dep_callst::const_iterator + it=control_dep_calls.begin(); + it!=control_dep_calls.end(); + ++it) + { + if(!control_deps.empty() || it!=control_dep_calls.begin()) + out << ","; + + out << (*it)->location_number << " [UNCONDITIONAL]"; + } + out << "\n"; } @@ -473,6 +483,16 @@ jsont variable_sensitivity_dependence_domaint::output_json( link["branch"]=json_stringt(branch.to_string()); } + for(const auto &target : control_dep_calls) + { + json_objectt &link=graph.push_back().make_object(); + link["locationNumber"]= + json_numbert(std::to_string(target->location_number)); + link["sourceLocation"]=json(target->source_location); + link["type"]=json_stringt("control"); + link["branch"]=json_stringt("UNCONDITIONAL"); + } + for(const auto &dep : domain_data_deps) { json_objectt &link=graph.push_back().make_object(); @@ -503,6 +523,9 @@ void variable_sensitivity_dependence_domaint::populate_dep_graph( for(const auto &c_dep : control_deps) dep_graph.add_dep(vs_dep_edget::kindt::CTRL, c_dep.first, this_loc); + for(const auto &c_dep : control_dep_calls) + dep_graph.add_dep(vs_dep_edget::kindt::CTRL, c_dep, this_loc); + for(const auto &d_dep : domain_data_deps) dep_graph.add_dep(vs_dep_edget::kindt::DATA, d_dep.first, this_loc); } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h index 66d0fbb892d..bb225c5070d 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -82,6 +82,7 @@ class variable_sensitivity_dependence_domaint: domain_data_deps.clear(); control_deps.clear(); control_dep_candidates.clear(); + control_dep_calls.clear(); } virtual void make_top() override @@ -92,6 +93,7 @@ class variable_sensitivity_dependence_domaint: domain_data_deps.clear(); control_deps.clear(); control_dep_candidates.clear(); + control_dep_calls.clear(); } virtual void make_entry() override @@ -171,6 +173,9 @@ class variable_sensitivity_dependence_domaint: typedef std::set control_dep_candidatest; control_dep_candidatest control_dep_candidates; + typedef std::set control_dep_callst; + control_dep_callst control_dep_calls; + void eval_data_deps( const exprt &expr, const namespacet &ns, data_depst &deps) const; @@ -187,7 +192,8 @@ class variable_sensitivity_dependence_domaint: bool merge_control_dependencies( const control_depst &other_control_deps, - const control_dep_candidatest &other_control_dep_candidates); + const control_dep_candidatest &other_control_dep_candidates, + const control_dep_callst &other_control_dep_calls); }; class variable_sensitivity_dependence_grapht: From fb494379c9321a42ad463f00a3cba2bcff2790ba Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 1 Aug 2018 15:54:02 +0100 Subject: [PATCH 266/342] Include GOTO guard expressions in variable sensitivity data dependencies --- .../variable-sensitivity-dependence-graph/main.c | 2 +- .../variable-sensitivity-dependence-graph/test.desc | 3 ++- .../variable_sensitivity_dependence_graph.cpp | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/main.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph/main.c index a92b484de5a..4f81ab8bfd6 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph/main.c +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/main.c @@ -28,7 +28,7 @@ void main(void) if (in == 1) ar[0]++; - if (in == 2) + if (out1 == 2) ar[1]++; out1 = ar[0]; diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc index cce09a2a906..4ad7af44264 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc @@ -1,4 +1,4 @@ -FUTURE +CORE main.c file1.c file2.c --dependence-graph-vs --structs --arrays --show EXIT=0 @@ -9,6 +9,7 @@ SIGNAL=0 ^Data dependencies: 4 \[st.b\], 53 \[st.b\]$ ^Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\]$ ^Data dependencies: 48 \[ar\[\(signed long int\)0\]\]$ +^Data dependencies: 1 \[out1\], 6 \[out1\], 53 \[out1\]$ ^Data dependencies: 48 \[ar\[\(signed long int\)1\]\]$ ^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\]$ ^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\]$ diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index 77116596dd2..a4bda2f6116 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -137,6 +137,10 @@ void variable_sensitivity_dependence_domaint::data_dependencies( eval_data_deps(arg, ns, domain_data_deps); } } + else if (to->is_goto()) + { + eval_data_deps(to->guard, ns, domain_data_deps); + } } void variable_sensitivity_dependence_domaint::control_dependencies( From a30aff6946285ede96443b6eaa03f89a3346a67c Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Thu, 2 Aug 2018 14:33:33 +0100 Subject: [PATCH 267/342] Fix variable sensitivity dependence graph regression test --- .../variable-sensitivity-dependence-graph-merge/test.desc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc index 19db1df596d..dad9a91adca 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc @@ -3,5 +3,5 @@ main.c --dependence-graph-vs --structs --arrays --verify EXIT=0 SIGNAL=0 -^\[main.assertion.1\] file .* function main, idx==1: Unknown$ +^\[main.assertion.1\] file .* function main, s_str.idx > 1: Unknown$ -- From 5f0484f0ef6950ca20bc91cfa4f4762037488102 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Thu, 2 Aug 2018 17:13:19 +0100 Subject: [PATCH 268/342] Ensure constant_array_abstract_object is in a valid state after calling make_top --- .../sensitivity-test-constants-array-loop/main.c | 13 +++++++++++++ .../sensitivity-test-constants-array-loop/test.desc | 9 +++++++++ .../variable-sensitivity/abstract_object.cpp | 8 ++++++++ src/analyses/variable-sensitivity/abstract_object.h | 1 + .../constant_array_abstract_object.cpp | 12 +++++++++++- .../constant_array_abstract_object.h | 3 ++- .../full_struct_abstract_object.h | 2 +- 7 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 regression/goto-analyzer/sensitivity-test-constants-array-loop/main.c create mode 100644 regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-loop/main.c b/regression/goto-analyzer/sensitivity-test-constants-array-loop/main.c new file mode 100644 index 00000000000..58248b83ae3 --- /dev/null +++ b/regression/goto-analyzer/sensitivity-test-constants-array-loop/main.c @@ -0,0 +1,13 @@ +static int array[2]; + +void main(void) +{ + + int i; + + for (i=0; i < 1; i++) + array[i] = 5; + + __CPROVER_assert(array[0] == 5, "array[0] == 5"); + __CPROVER_assert(array[1] == 5, "array[1] == 5"); +} diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc new file mode 100644 index 00000000000..37736c7bba5 --- /dev/null +++ b/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc @@ -0,0 +1,9 @@ +CORE +main.c +--variable --arrays --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] .* array\[0\] == 5: Unknown$ +^\[main.assertion.2\] .* array\[1\] == 5: Unknown$ +-- +^warning: ignoring diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index cb3de4d05eb..cfd0709853e 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -294,6 +294,14 @@ bool abstract_objectt::is_bottom() const return bottom; } +/// \brief Verify the internal structure of an abstract_object is correct +/// \return true if the abstract_object is correctly constructed, or false +/// otherwise +bool abstract_objectt::verify() const +{ + return !(top && bottom); +} + /*******************************************************************\ Function: abstract_objectt::to_constant diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 02602a3bf8f..42de1c0a49d 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -92,6 +92,7 @@ class abstract_objectt:public std::enable_shared_from_this const typet &type() const; virtual bool is_top() const; virtual bool is_bottom() const; + virtual bool verify() const; virtual void get_statistics( abstract_object_statisticst &statistics, diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 1c9d101acce..860bc19a109 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -112,7 +112,17 @@ bool constant_array_abstract_objectt::verify() const { // 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(); + return array_abstract_objectt::verify() && + (is_top() || is_bottom()) == map.empty(); +} + +/// \brief Perform any additional structural modifications when setting this +/// object to TOP +void constant_array_abstract_objectt::make_top_internal() +{ + // A structural invariant of constant_array_abstract_objectt is that + // (is_top() || is_bottom()) => map.empty() + map.clear(); } /*******************************************************************\ diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index 8d68f0015cd..c6bf182ba10 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -63,7 +63,8 @@ class constant_array_abstract_objectt:public array_abstract_objectt virtual abstract_object_pointert merge( abstract_object_pointert other) const override; - bool verify() const; + virtual bool verify() const override; + virtual void make_top_internal() override; virtual bool eval_index( const index_exprt &index, diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 45d3a5eae1c..187e5a12b28 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -75,7 +75,7 @@ class full_struct_abstract_objectt:public struct_abstract_objectt const abstract_object_pointert value, bool merging_write) const override; - bool verify() const; + virtual bool verify() const override; // Set the state of this to the merge result of op1 and op2 and // return if the result is different from op1 virtual abstract_object_pointert merge( From 37260d44aa126bfb9d4081c78a47167af7c4a3c7 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 8 Aug 2018 13:02:53 +0100 Subject: [PATCH 269/342] Fix variable sensitvity to build with XCode 9 --- src/analyses/variable-sensitivity/data_dependency_context.h | 2 +- src/analyses/variable-sensitivity/write_location_context.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/data_dependency_context.h b/src/analyses/variable-sensitivity/data_dependency_context.h index 5ef388c9c0e..10341faa40a 100644 --- a/src/analyses/variable-sensitivity/data_dependency_context.h +++ b/src/analyses/variable-sensitivity/data_dependency_context.h @@ -84,7 +84,7 @@ class data_dependency_contextt: public: bool operator()( goto_programt::const_targett instruction, - goto_programt::const_targett other_instruction) + goto_programt::const_targett other_instruction) const { return instruction->location_number> other_instruction->location_number; diff --git a/src/analyses/variable-sensitivity/write_location_context.cpp b/src/analyses/variable-sensitivity/write_location_context.cpp index 4954eac7d22..14494a35732 100644 --- a/src/analyses/variable-sensitivity/write_location_context.cpp +++ b/src/analyses/variable-sensitivity/write_location_context.cpp @@ -286,7 +286,7 @@ bool write_location_contextt::has_been_modified( public: bool operator()( goto_programt::const_targett instruction, - goto_programt::const_targett other_instruction) + goto_programt::const_targett other_instruction) const { return instruction->location_number> other_instruction->location_number; From 918f319a8f032d52e46c70f9c96dd711fa954e80 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Thu, 9 Aug 2018 15:30:03 +0100 Subject: [PATCH 270/342] Unconditional control dependency fix --- .../test.desc | 11 ++++++ .../variable_sensitivity_dependence_graph.cpp | 38 +++++++++++++++---- .../variable_sensitivity_dependence_graph.h | 7 +++- 3 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph15/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph15/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph15/test.desc new file mode 100644 index 00000000000..d9a7d78a58f --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph15/test.desc @@ -0,0 +1,11 @@ +CORE +../dependence-graph15/main.c +--show --dependence-graph-vs +activate-multi-line-match +^EXIT=0$ +^SIGNAL=0$ +Control dependencies: [0-9]+ \[UNCONDITIONAL\]\n(.*\n){2,3}.*g_out2 = t1; +Control dependencies: [0-9]+ \[TRUE\]\n(.*\n){2,3}.*g_out1 = t2; +Control dependencies: [0-9]+ \[FALSE\]\n(.*\n){2,3}.*g_out1 = 0; +-- +^warning: ignoring diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index a4bda2f6116..4967c6a0d4c 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -97,7 +97,8 @@ void variable_sensitivity_dependence_domaint::transform( if(s->merge_control_dependencies( control_deps, control_dep_candidates, - control_dep_calls)) + control_dep_calls, + control_dep_call_candidates)) s->has_changed=true; control_deps.clear(); @@ -105,6 +106,9 @@ void variable_sensitivity_dependence_domaint::transform( control_dep_calls.clear(); control_dep_calls.insert(from); + + control_dep_call_candidates.clear(); + control_dep_call_candidates.insert(from); } } else @@ -161,6 +165,8 @@ void variable_sensitivity_dependence_domaint::control_dependencies( // Add new candidates + PRECONDITION(!control_dep_call_candidates.empty()); + if(from->is_goto() || from->is_assume()) control_dep_candidates.insert(from); else if(from->is_end_function()) @@ -168,12 +174,10 @@ void variable_sensitivity_dependence_domaint::control_dependencies( control_deps.clear(); control_dep_candidates.clear(); control_dep_calls.clear(); + control_dep_call_candidates.clear(); return; } - if(control_dep_candidates.empty()) - return; - // Compute postdominators if needed const goto_functionst &goto_functions=dep_graph.goto_functions; @@ -242,10 +246,18 @@ void variable_sensitivity_dependence_domaint::control_dependencies( } control_deps.insert(std::make_pair(cd, branch)); - control_dep_calls.clear(); } } + if(control_deps.empty()) + { + util_inplace_set_union(control_dep_calls, control_dep_call_candidates); + } + else + { + control_dep_calls.clear(); + } + // add edges to the graph for(const auto &c_dep : control_deps) dep_graph.add_dep(vs_dep_edget::kindt::CTRL, c_dep.first, to); @@ -254,7 +266,8 @@ void variable_sensitivity_dependence_domaint::control_dependencies( bool variable_sensitivity_dependence_domaint::merge_control_dependencies( const control_depst &other_control_deps, const control_dep_candidatest &other_control_dep_candidates, - const control_dep_callst &other_control_dep_calls) + const control_dep_callst &other_control_dep_calls, + const control_dep_callst &other_control_dep_call_candidates) { bool changed=false; @@ -313,6 +326,16 @@ bool variable_sensitivity_dependence_domaint::merge_control_dependencies( changed|=n!=control_dep_calls.size(); + // Merge call control dependency candidates + + n=control_dep_call_candidates.size(); + + control_dep_call_candidates.insert( + other_control_dep_call_candidates.begin(), + other_control_dep_call_candidates.end()); + + changed|=n!=control_dep_call_candidates.size(); + return changed; } @@ -351,7 +374,8 @@ bool variable_sensitivity_dependence_domaint::merge( changed |= merge_control_dependencies( cast_b.control_deps, cast_b.control_dep_candidates, - cast_b.control_dep_calls); + cast_b.control_dep_calls, + cast_b.control_dep_call_candidates); has_changed=false; has_values=tvt::unknown(); diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h index bb225c5070d..02e8f8b672c 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -12,6 +12,7 @@ #include #include +#include #include @@ -83,6 +84,7 @@ class variable_sensitivity_dependence_domaint: control_deps.clear(); control_dep_candidates.clear(); control_dep_calls.clear(); + control_dep_call_candidates.clear(); } virtual void make_top() override @@ -94,6 +96,7 @@ class variable_sensitivity_dependence_domaint: control_deps.clear(); control_dep_candidates.clear(); control_dep_calls.clear(); + control_dep_call_candidates.clear(); } virtual void make_entry() override @@ -175,6 +178,7 @@ class variable_sensitivity_dependence_domaint: typedef std::set control_dep_callst; control_dep_callst control_dep_calls; + control_dep_callst control_dep_call_candidates; void eval_data_deps( const exprt &expr, const namespacet &ns, data_depst &deps) const; @@ -193,7 +197,8 @@ class variable_sensitivity_dependence_domaint: bool merge_control_dependencies( const control_depst &other_control_deps, const control_dep_candidatest &other_control_dep_candidates, - const control_dep_callst &other_control_dep_calls); + const control_dep_callst &other_control_dep_calls, + const control_dep_callst &other_control_dep_call_candidates); }; class variable_sensitivity_dependence_grapht: From a7f7c752be8bbc94f96147395c714c795c360210 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 8 Aug 2018 17:30:48 +0100 Subject: [PATCH 271/342] Track only immediate dependencies in variable sensitivity dependence graph. Previously the variable sensitivity dependence graph would track both immediate and transitive dependencies. Transitive dependencies are not needed and can be calculated by other means. This change brings variable sensitivity dependence graph into line with the behaviour of the old dependence graph code. --- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 4 +-- .../data_dependency_context.cpp | 33 +++++++++++++++++-- .../data_dependency_context.h | 16 ++++++--- 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc b/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc index c438c60068d..9ebe48039a5 100644 --- a/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc +++ b/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc @@ -7,6 +7,6 @@ EXIT=0 SIGNAL=0 st \(\) -> \{.a=.* @ \[2, 47\]\[Data dependencies: 47, 2\]\[Data dominators: \], .b=.* @ \[5, 47\]\[Data dependencies: 47, 5\]\[Data dominators: \]\} @ \[2, 5, 47\]\[Data dependencies: 47, 5, 2\]\[Data dominators: 47\] ar \(\) -> \{\[0\] = .* @ \[11, 42\]\[Data dependencies: 42, 11\]\[Data dominators: \]\n\[1\] = .* @ \[14, 42\]\[Data dependencies: 42, 14\]\[Data dominators: \]\n\} @ \[11, 14, 42\]\[Data dependencies: 42, 14, 11\]\[Data dominators: 42\] -arr \(\) -> \{\[0\] = .* @ \[19\]\[Data dependencies: 19\]\[Data dominators: 19\]\n\[1\] = .* @ \[20\]\[Data dependencies: 20\]\[Data dominators: 20\]\n\[2\] = .* @ \[21, 23\]\[Data dependencies: 23, 21, 20\]\[Data dominators: \]\n\} @ \[21, 23\]\[Data dependencies: 43, 23, 21, 20, 19\]\[Data dominators: 43\] +arr \(\) -> \{\[0\] = .* @ \[19\]\[Data dependencies: 19\]\[Data dominators: 19\]\n\[1\] = .* @ \[20\]\[Data dependencies: 20\]\[Data dominators: 20\]\n\[2\] = .* @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: \]\n\} @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: 43\] -- ^warning: ignoring diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc index 614e1f078f9..c9f81268709 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc @@ -16,7 +16,7 @@ Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int Data dependencies: 19 \[arr\[\(signed long int\)1\]\] Data dependencies: 18 \[arr\[\(signed long int\)0\]\] Data dependencies: 19 \[arr\[\(signed long int\)1\]\] -Data dependencies: 19 \[arr\[\(signed long int\)2\]\], 20 \[arr\[\(signed long int\)2\]\], 22 \[arr\[\(signed long int\)2\]\] +Data dependencies: 20 \[arr\[\(signed long int\)2\]\], 22 \[arr\[\(signed long int\)2\]\] Data dependencies: 1 \[st.a\], 53 \[st.a\], 57 \[st.a\] Data dependencies: 4 \[st.b\], 53 \[st.b\], 60 \[st.b\] Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\], 57 \[st.a\], 60 \[st.b\] diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc index 4ad7af44264..017a185317f 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc @@ -9,7 +9,7 @@ SIGNAL=0 ^Data dependencies: 4 \[st.b\], 53 \[st.b\]$ ^Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\]$ ^Data dependencies: 48 \[ar\[\(signed long int\)0\]\]$ -^Data dependencies: 1 \[out1\], 6 \[out1\], 53 \[out1\]$ +^Data dependencies: 6 \[out1\]$ ^Data dependencies: 48 \[ar\[\(signed long int\)1\]\]$ ^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\]$ ^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\]$ @@ -17,7 +17,7 @@ SIGNAL=0 ^Data dependencies: 19 \[arr\[\(signed long int\)1\]\]$ ^Data dependencies: 18 \[arr\[\(signed long int\)0\]\]$ ^Data dependencies: 19 \[arr\[\(signed long int\)1\]\]$ -^Data dependencies: 19 \[arr\[\(signed long int\)2\]\], 20 \[arr\[\(signed long int\)2\]\], 22 \[arr\[\(signed long int\)2\]\]$ +^Data dependencies: 20 \[arr\[\(signed long int\)2\]\], 22 \[arr\[\(signed long int\)2\]\]$ ^Data dependencies: 1 \[st.a\], 53 \[st.a\], 57 \[st.a\]$ ^Data dependencies: 4 \[st.b\], 53 \[st.b\], 60 \[st.b\]$ ^Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\], 57 \[st.a\], 60 \[st.b\]$ diff --git a/src/analyses/variable-sensitivity/data_dependency_context.cpp b/src/analyses/variable-sensitivity/data_dependency_context.cpp index 3c326d67810..bd63f693632 100644 --- a/src/analyses/variable-sensitivity/data_dependency_context.cpp +++ b/src/analyses/variable-sensitivity/data_dependency_context.cpp @@ -129,6 +129,35 @@ abstract_object_pointert data_dependency_contextt::insert_data_deps( return result; } +/** + * Set the given set of data dependencies for this data_dependency_context + * object. + * + * \param dependencies the set of dependencies to set + * \return a new data_dependency_context if new dependencies were set, + * or 'this' if the dependencies were not changed. + */ +abstract_object_pointert data_dependency_contextt::set_data_deps( + const dependencest &dependencies) const +{ + // If the dependencies will not change, just return 'this' + if(data_deps == dependencies) + return shared_from_this(); + + const auto &result= + std::dynamic_pointer_cast(mutable_clone()); + + result->data_deps = dependencies; + + // If this is the first write to the context then it is also used as + // the initial set of data dependency dominators as well. + if(data_deps.empty()) + { + result->data_dominators = dependencies; + } + return result; +} + /** * A helper function to evaluate writing to a component of an * abstract object. More precise abstractions may override this to @@ -161,7 +190,7 @@ abstract_object_pointert data_dependency_contextt::write( const auto cast_value= std::dynamic_pointer_cast(value); - return updated_parent->insert_data_deps(cast_value->data_deps); + return updated_parent->set_data_deps(cast_value->data_deps); } /** @@ -185,7 +214,7 @@ data_dependency_contextt::update_location_context( this->write_location_contextt::update_location_context( locations, update_sub_elements)); - return updated_parent->insert_data_deps(locations); + return updated_parent->set_data_deps(locations); } /** diff --git a/src/analyses/variable-sensitivity/data_dependency_context.h b/src/analyses/variable-sensitivity/data_dependency_context.h index 10341faa40a..6cd7743d7af 100644 --- a/src/analyses/variable-sensitivity/data_dependency_context.h +++ b/src/analyses/variable-sensitivity/data_dependency_context.h @@ -97,17 +97,25 @@ class data_dependency_contextt: abstract_object_pointert insert_data_deps( const dependencest &dependencies) const; + abstract_object_pointert set_data_deps( + const dependencest &dependencies) const; + abstract_object_pointert insert_data_deps(const locationst &locations) const { // `locationst` is unsorted, so convert this to a sorted `dependenciest` - dependencest dependencies; - - for(const auto l : locations) - dependencies.insert(l); + dependencest dependencies(locations.begin(), locations.end()); return insert_data_deps(dependencies); } + abstract_object_pointert set_data_deps(const locationst &locations) const + { + // `locationst` is unsorted, so convert this to a sorted `dependenciest` + dependencest dependencies(locations.begin(), locations.end()); + + return set_data_deps(dependencies); + } + }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_DATA_DEPENDENCY_CONTEXT_H From 27a8b2198b22d5d2fd49ebb63b7863075ccc1163 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 10 Aug 2018 11:22:53 +0100 Subject: [PATCH 272/342] Fix dependence graph precondition failure in VSB dependence graph --- .../variable_sensitivity_dependence_graph.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index 4967c6a0d4c..36e594065f2 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -165,8 +165,6 @@ void variable_sensitivity_dependence_domaint::control_dependencies( // Add new candidates - PRECONDITION(!control_dep_call_candidates.empty()); - if(from->is_goto() || from->is_assume()) control_dep_candidates.insert(from); else if(from->is_end_function()) From 06952e0b68232738b03273a9b7ef76c08f51db20 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Tue, 7 Aug 2018 17:00:56 +0100 Subject: [PATCH 273/342] Initialise is_bottom in abstract_environmentt --- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 6 ++++++ src/analyses/variable-sensitivity/abstract_enviroment.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 4117c99189b..219c88b2b23 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -767,3 +767,9 @@ abstract_environmentt::gather_statistics(const namespacet &ns) const } return statistics; } + +abstract_environmentt::abstract_environmentt() +: bottom(false) +{ + +} diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index bb186580999..7a3868fbe82 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -23,6 +23,7 @@ class abstract_environmentt { public: + abstract_environmentt(); // These three are really the heart of the method virtual abstract_object_pointert eval( const exprt &expr, const namespacet &ns) const; From d108527ef04772599f50f16e036ffb78ebe1bcbc Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 15 Aug 2018 16:00:33 +0100 Subject: [PATCH 274/342] Fixup incorrect itterator comparison in data_dependency_context Because the entries in dependency sets are locationt's (and therefore itterators form potentially different collections) it's not safe to directly compare dependency sets. --- .../data_dependency_context.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/data_dependency_context.cpp b/src/analyses/variable-sensitivity/data_dependency_context.cpp index bd63f693632..234cdc2e8d3 100644 --- a/src/analyses/variable-sensitivity/data_dependency_context.cpp +++ b/src/analyses/variable-sensitivity/data_dependency_context.cpp @@ -141,9 +141,20 @@ abstract_object_pointert data_dependency_contextt::set_data_deps( const dependencest &dependencies) const { // If the dependencies will not change, just return 'this' - if(data_deps == dependencies) + abstract_objectt::locationst intersection; + + std::set_intersection( + data_deps.cbegin(), + data_deps.cend(), + dependencies.cbegin(), + dependencies.cend(), + std::inserter(intersection, intersection.end()), + location_ordert()); + if(intersection.size()==data_deps.size() && + intersection.size()==dependencies.size()) return shared_from_this(); + const auto &result= std::dynamic_pointer_cast(mutable_clone()); From 312b598afaa3027bed129c443c3d45db36a6e9e6 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Thu, 16 Aug 2018 10:28:32 +0100 Subject: [PATCH 275/342] Add a module_dependencies.txt to variable sensitivity domain --- src/analyses/variable-sensitivity/module_dependencies.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/analyses/variable-sensitivity/module_dependencies.txt diff --git a/src/analyses/variable-sensitivity/module_dependencies.txt b/src/analyses/variable-sensitivity/module_dependencies.txt new file mode 100644 index 00000000000..0e78852b13c --- /dev/null +++ b/src/analyses/variable-sensitivity/module_dependencies.txt @@ -0,0 +1,4 @@ +analyses +goto-programs +langapi # should go away +util From 70bb1cea0e05a7f412475623dacc298c6efc6406 Mon Sep 17 00:00:00 2001 From: Petr Bauch Date: Fri, 7 Sep 2018 09:26:18 +0100 Subject: [PATCH 276/342] Tools to build intersection of intervals satisfying bool expressions --- .../variable-sensitivity/abstract_object.cpp | 82 +++++ .../variable-sensitivity/abstract_object.h | 22 +- .../interval_abstract_value.cpp | 182 ++++++++++- .../interval_abstract_value.h | 4 + unit/Makefile | 1 + .../interval_abstract_value/meet.cpp | 287 ++++++++++++++++++ 6 files changed, 576 insertions(+), 2 deletions(-) create mode 100644 unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index cfd0709853e..b77326a41e9 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -83,6 +83,20 @@ abstract_objectt::abstract_objectt( t(expr.type()), bottom(false), top(true) {} +/// Ctor for building object of types that differ from the types of input +/// expressions +/// \param type explicitly declared type the resulting object should have +/// \param expr expression used to build the object +/// \param environment abstract environment to evaluate the expression +/// \param ns namespace to uncover names inside the expression +abstract_objectt::abstract_objectt( + const typet &type, + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns): + t(type), bottom(false), top(true) +{} + /*******************************************************************\ Function: abstract_objectt::type @@ -165,6 +179,44 @@ abstract_object_pointert abstract_objectt::abstract_object_merge_internal( return shared_from_this(); } +/// Base implementation of the meet operation: only used if no more precise +/// abstraction can be used, can only result in {TOP, BOTTOM, one of the +/// original objects} +/// \param other pointer to the abstract object to meet +/// \return the resulting abstract object pointer +abstract_object_pointert +abstract_objectt::meet(const abstract_object_pointert &other) const +{ + return abstract_object_meet(other); +} + +/// Helper function for base meet. Two cases: return itself (if trivially +/// contained in other); return BOTTOM otherwise. +/// \param other pointer to the other object +/// \return the resulting object +abstract_object_pointert abstract_objectt::abstract_object_meet( + const abstract_object_pointert &other) const +{ + if(is_bottom() || other->top) + return this->abstract_object_meet_internal(other); + + internal_abstract_object_pointert met = mutable_clone(); + met->bottom = true; + met->top = false; + return met->abstract_object_meet_internal(other); +} + +/// Helper function for base meet, in case additional work was needed. Base +/// implementation simply return pointer to itself. +/// \param other pointer to the other object +/// \return the resulting object +abstract_object_pointert abstract_objectt::abstract_object_meet_internal( + const abstract_object_pointert &other) const +{ + // Default implementation + return shared_from_this(); +} + /*******************************************************************\ Function: abstract_objectt::expression_transform @@ -408,6 +460,36 @@ bool abstract_objectt::should_use_base_merge( return is_top() || other->is_bottom() || other->is_top(); } +/// Interface method for the meet operation. Decides whether to use the base +/// implementation or if a more precise abstraction is attainable. +/// \param op1 lhs object for meet +/// \param op2 rhs object for meet +/// \param out_modifications reference to a flag indicating modification (result +/// is not op1) +/// \return resulting object after meet +abstract_object_pointert abstract_objectt::meet( + abstract_object_pointert op1, + abstract_object_pointert op2, + bool &out_modifications) +{ + abstract_object_pointert result=op1->should_use_base_meet(op2)? + op1->abstract_object_meet(op2):op1->meet(op2); + // If no modifications, we will return the original pointer + out_modifications=result!=op1; + + return result; +} + +/// Helper function to decide if base meet implementation should be used +/// \param other pointer to the other object to meet +/// \return true if base implementation would yield the most precise +/// abstraction anyway +bool abstract_objectt::should_use_base_meet( + const abstract_object_pointert &other) const +{ + return is_bottom() || other->is_bottom() || other->is_top(); +} + /** * Update the location context for an abstract object, potentially * propogating the update to any children of this abstract object. diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 42de1c0a49d..ac55b5e5601 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -86,6 +86,11 @@ class abstract_objectt:public std::enable_shared_from_this const exprt &expr, const abstract_environmentt &environment, const namespacet &ns); + abstract_objectt( + const typet &type, + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); virtual ~abstract_objectt() {} @@ -128,7 +133,7 @@ class abstract_objectt:public std::enable_shared_from_this typedef std::set locationst; typedef sharing_mapt shared_mapt; - + static void dump_map(std::ostream out, const shared_mapt &m); static void dump_map_diff( std::ostream out, const shared_mapt &m1, const shared_mapt &m2); @@ -159,6 +164,14 @@ class abstract_objectt:public std::enable_shared_from_this abstract_object_pointert op2, bool &out_modifications); + static abstract_object_pointert meet( + abstract_object_pointert op1, + abstract_object_pointert op2, + bool &out_modifications); + + virtual abstract_object_pointert + meet(const abstract_object_pointert &other) const; + virtual abstract_object_pointert update_location_context( const locationst &locations, const bool update_sub_elements) const; @@ -226,6 +239,8 @@ class abstract_objectt:public std::enable_shared_from_this // part of an abstract_object_merge virtual abstract_object_pointert abstract_object_merge_internal( const abstract_object_pointert other) const; + virtual abstract_object_pointert + abstract_object_meet_internal(const abstract_object_pointert &other) const; protected: template @@ -248,6 +263,11 @@ class abstract_objectt:public std::enable_shared_from_this // Sets the state of this object virtual abstract_object_pointert merge(abstract_object_pointert other) const; + abstract_object_pointert + abstract_object_meet(const abstract_object_pointert &other) const; + + bool should_use_base_meet(const abstract_object_pointert &other) const; + template static bool merge_maps( const std::map &map1, diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index 189bb685ca0..93bf136d577 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -7,6 +7,7 @@ \*******************************************************************/ #include +#include #include #include @@ -24,6 +25,82 @@ static inline exprt look_through_casts(exprt e) return e; } +static inline bool +bvint_value_is_max(const typet &type, const mp_integer &value) +{ + PRECONDITION(type.id() == ID_signedbv || type.id() == ID_unsignedbv); + if(type.id() == ID_signedbv) + { + return to_signedbv_type(type).largest() == value; + } + else + { + return to_unsignedbv_type(type).largest() == value; + } +} + +static inline bool +bvint_value_is_min(const typet &type, const mp_integer &value) +{ + PRECONDITION(type.id() == ID_signedbv || type.id() == ID_unsignedbv); + if(type.id() == ID_signedbv) + { + return to_signedbv_type(type).smallest() == value; + } + else + { + return to_unsignedbv_type(type).smallest() == value; + } +} + +static inline constant_interval_exprt +interval_from_x_le_value(const exprt &value) +{ + return constant_interval_exprt(min_exprt(value.type()), value); +} + +static inline constant_interval_exprt +interval_from_x_ge_value(const exprt &value) +{ + return constant_interval_exprt(value, max_exprt(value.type())); +} + +static inline mp_integer force_value_from_expr(const exprt &value) +{ + PRECONDITION(constant_interval_exprt::is_int(value.type())); + optionalt maybe_integer_value = numeric_cast(value); + INVARIANT(maybe_integer_value.has_value(), "Input has to have a value"); + return maybe_integer_value.value(); +} + +static inline constant_interval_exprt +interval_from_x_lt_value(const exprt &value) +{ + mp_integer integer_value = force_value_from_expr(value); + if(!bvint_value_is_min(value.type(), integer_value)) + return constant_interval_exprt( + min_exprt(value.type()), from_integer(integer_value - 1, value.type())); + else + return constant_interval_exprt().bottom(); +} + +static inline constant_interval_exprt +interval_from_x_gt_value(const exprt &value) +{ + mp_integer integer_value = force_value_from_expr(value); + if(!bvint_value_is_max(value.type(), integer_value)) + return constant_interval_exprt( + from_integer(integer_value + 1, value.type()), max_exprt(value.type())); + else + return constant_interval_exprt().bottom(); +} + +static inline bool represents_interval(exprt e) +{ + e = look_through_casts(e); + return (e.id() == ID_constant_interval || e.id() == ID_constant); +} + static inline constant_interval_exprt make_interval_expr(exprt e) { e = look_through_casts(e); @@ -42,6 +119,59 @@ static inline constant_interval_exprt make_interval_expr(exprt e) } } +static inline irep_idt invert_relation(const irep_idt &relation) +{ + PRECONDITION( + relation == ID_le || relation == ID_lt || relation == ID_ge || + relation == ID_gt || relation == ID_equal); + if(relation == ID_le) + return ID_ge; + if(relation == ID_ge) + return ID_le; + if(relation == ID_lt) + return ID_gt; + if(relation == ID_gt) + return ID_lt; + return relation; +} + +/// Builds an interval representing all values satisfying the input expression. +/// The expression is expected to be a comparison between an integer constant +/// and a variable (symbol) +/// \param e the relation expression that should be satisfied +/// \return the constant interval expression representing the values +static inline constant_interval_exprt interval_from_relation(const exprt &e) +{ + PRECONDITION(e.operands().size() == 2); + const auto &relation = e.id(); + const auto &lhs = e.op0(); + const auto &rhs = e.op1(); + PRECONDITION( + relation == ID_le || relation == ID_lt || relation == ID_ge || + relation == ID_gt || relation == ID_equal); + PRECONDITION(lhs.id() == ID_constant || lhs.id() == ID_symbol); + PRECONDITION(rhs.id() == ID_constant || rhs.id() == ID_symbol); + PRECONDITION(lhs.id() != rhs.id()); + + const auto the_constant_part_of_the_relation = + (rhs.id() == ID_symbol ? lhs : rhs); + const auto maybe_inverted_relation = + (rhs.id() == ID_symbol ? invert_relation(relation) : relation); + + if(maybe_inverted_relation == ID_le) + return interval_from_x_le_value(the_constant_part_of_the_relation); + if(maybe_inverted_relation == ID_lt) + return interval_from_x_lt_value(the_constant_part_of_the_relation); + if(maybe_inverted_relation == ID_ge) + return interval_from_x_ge_value(the_constant_part_of_the_relation); + if(maybe_inverted_relation == ID_gt) + return interval_from_x_gt_value(the_constant_part_of_the_relation); + INVARIANT( + maybe_inverted_relation == ID_equal, "We excluded other cases above"); + return constant_interval_exprt( + the_constant_part_of_the_relation, the_constant_part_of_the_relation); +} + interval_abstract_valuet::interval_abstract_valuet(typet t) : abstract_valuet(t), interval(t) {} @@ -258,11 +388,61 @@ abstract_object_pointert interval_abstract_valuet::merge_intervals( } } +abstract_object_pointert +interval_abstract_valuet::meet(const abstract_object_pointert &other) const +{ + interval_abstract_value_pointert cast_other = + std::dynamic_pointer_cast(other); + if(cast_other) + { + return meet_intervals(cast_other); + } + else + { + return abstract_valuet::meet(other); + } +} + +/// Meet another interval abstract object with this one +/// \param other The interval abstract object to meet with +/// \return This if the other interval subsumes this, +/// other if this subsumes other. +/// Otherwise, a new interval abstract object +/// with the intersection interval (of this and other) +abstract_object_pointert interval_abstract_valuet::meet_intervals( + interval_abstract_value_pointert other) const +{ + if(is_bottom() || other->interval.contains(interval)) + { + return shared_from_this(); + } + else if(other->is_bottom() || interval.contains(other->interval)) + { + return other; + } + else + { + auto lower_bound = constant_interval_exprt::get_max( + interval.get_lower(), other->interval.get_lower()); + auto upper_bound = constant_interval_exprt::get_min( + interval.get_upper(), other->interval.get_upper()); + + if(constant_interval_exprt::less_than(upper_bound, lower_bound)) + return std::make_shared( + interval.type(), false, true); + return std::make_shared( + constant_interval_exprt(lower_bound, upper_bound), + std::max(merge_count, other->merge_count) + 1); + } +} + interval_abstract_valuet::interval_abstract_valuet( const exprt e, const abstract_environmentt &environment, const namespacet &ns) - : interval_abstract_valuet(make_interval_expr(e)) + : interval_abstract_valuet( + represents_interval(e) ? make_interval_expr(e) + : interval_from_relation(e)) {} interval_abstract_valuet::interval_abstract_valuet( diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h index 7fe27989c1e..56f91e50969 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.h +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -64,10 +64,14 @@ class interval_abstract_valuet:public abstract_valuet CLONE virtual abstract_object_pointert merge( abstract_object_pointert other) const override; + abstract_object_pointert + meet(const abstract_object_pointert &other) const override; private : abstract_object_pointert merge_intervals( interval_abstract_value_pointert other) const; + abstract_object_pointert meet_intervals( + interval_abstract_value_pointert other) const; constant_interval_exprt interval; diff --git a/unit/Makefile b/unit/Makefile index 1d11afcf900..3293f97ada7 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -17,6 +17,7 @@ SRC += analyses/ai/ai.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/interval_abstract_value/meet.cpp \ analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp \ analyses/variable-sensitivity/last_written_location.cpp \ analyses/variable-sensitivity/write_stack.cpp \ diff --git a/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp b/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp new file mode 100644 index 00000000000..386664c044c --- /dev/null +++ b/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp @@ -0,0 +1,287 @@ +/*******************************************************************\ + + Module: Unit tests for interval_abstract_valuet::meet + + Author: DiffBlue Limited. All rights reserved. + +\*******************************************************************/ + +#include + +#include +#include +#include + +SCENARIO( + "meet_interval_abstract_value", + "[core][analyses][variable-sensitivity][interval_abstract_value][meet]") +{ + GIVEN("An environment with two intervals: 1--10 and 2--5") + { + const typet type = signedbv_typet(32); + const exprt val1 = from_integer(1, type); + REQUIRE(constant_interval_exprt::is_int(val1.type())); + const exprt val10 = from_integer(10, type); + const exprt val11 = from_integer(11, type); + REQUIRE(constant_interval_exprt::is_int(val10.type())); + const auto interval1_10 = constant_interval_exprt(val1, val10); + + const auto varx = symbol_exprt(type); + const auto x_le_10 = binary_relation_exprt(varx, ID_le, val10); + const auto lt_10_x = binary_relation_exprt(val10, ID_le, varx); + + const exprt val2 = from_integer(2, type); + const exprt val15 = from_integer(15, type); + const auto interval2_15 = constant_interval_exprt(val2, val15); + + const auto interval1_2 = constant_interval_exprt(val1, val2); + const auto interval10_15 = constant_interval_exprt(val10, val15); + + const auto temp_expr = unsignedbv_typet(32); + const auto max_value = temp_expr.largest_expr(); + const auto x_ge_max = binary_relation_exprt(varx, ID_ge, max_value); + const auto x_gt_max = binary_relation_exprt(varx, ID_gt, max_value); + + abstract_environmentt enviroment; + enviroment.make_top(); + symbol_tablet symbol_table; + namespacet ns(symbol_table); + + WHEN( + "meeting constant AO with interval " + "with a constant AO with the same interval") + { + abstract_object_pointert op1 = std::make_shared( + interval1_10, enviroment, ns); + abstract_object_pointert op2 = std::make_shared( + interval1_10, enviroment, ns); + + bool modified; + abstract_object_pointert result = + abstract_objectt::meet(op1, op2, modified); + + 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); + + // Correctness of meet + REQUIRE_FALSE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + REQUIRE(cast_result->get_interval() == interval1_10); + + // Is optimal + REQUIRE(result == op1); + } + } + WHEN( + "meeting constant AO with interval " + "with a constant AO with the different interval") + { + abstract_object_pointert op1 = + std::make_shared(interval1_2, enviroment, ns); + abstract_object_pointert op2 = std::make_shared( + interval10_15, enviroment, ns); + + bool modified; + abstract_object_pointert result = + abstract_objectt::meet(op1, op2, modified); + + const auto &cast_result = + std::dynamic_pointer_cast(result); + + THEN("A new constant abstract object set to bottom should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of meet + REQUIRE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE(cast_result->is_bottom()); + + // Intersection should have this exact value + REQUIRE_FALSE(result == op1); + } + } + WHEN( + "meeting constant AO with interval " + "with a constant AO with the different interval") + { + abstract_object_pointert op1 = std::make_shared( + interval1_10, enviroment, ns); + abstract_object_pointert op2 = std::make_shared( + interval2_15, enviroment, ns); + + const auto interval2_10 = constant_interval_exprt(val2, val10); + abstract_object_pointert op3 = std::make_shared( + interval2_10, enviroment, ns); + + bool modified; + abstract_object_pointert result = + abstract_objectt::meet(op1, op2, modified); + + 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); + + // Correctness of meet + REQUIRE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + + // Intersection should have this exact value + REQUIRE(cast_result->get_interval() == interval2_10); + } + } + WHEN( + "build constant AO with interval using le_expression " + "then meet with a constant AO with the different interval") + { + abstract_object_pointert op1 = + std::make_shared(x_le_10, enviroment, ns); + abstract_object_pointert op2 = std::make_shared( + interval2_15, enviroment, ns); + + const auto interval2_10 = constant_interval_exprt(val2, val10); + abstract_object_pointert op3 = std::make_shared( + interval2_10, enviroment, ns); + + bool modified; + abstract_object_pointert result = + abstract_objectt::meet(op1, op2, modified); + + const auto &cast_result = + std::dynamic_pointer_cast(result); + + THEN( + "A new constant abstract object set to intersection should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of meet + REQUIRE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + + // Intersection should have this exact value + REQUIRE(cast_result->get_interval() == interval2_10); + } + } + WHEN( + "build constant AO with interval using lt_expression " + "then meet with a constant AO with the different interval") + { + abstract_object_pointert op1 = + std::make_shared(lt_10_x, enviroment, ns); + abstract_object_pointert op2 = std::make_shared( + interval2_15, enviroment, ns); + + const auto interval11_15 = constant_interval_exprt(val11, val15); + abstract_object_pointert op3 = std::make_shared( + interval11_15, enviroment, ns); + + bool modified; + abstract_object_pointert result = + abstract_objectt::meet(op1, op2, modified); + + const auto &cast_result = + std::dynamic_pointer_cast(result); + + THEN( + "A new constant abstract object set to intersection should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of meet + REQUIRE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + + // Intersection should have this exact value + REQUIRE(cast_result->get_interval() == interval11_15); + } + } + WHEN( + "build constant AO with interval using ge_max_expression " + "then meet with a constant AO with the different interval") + { + abstract_object_pointert op1 = + std::make_shared(lt_10_x, enviroment, ns); + abstract_object_pointert op2 = + std::make_shared(x_ge_max, enviroment, ns); + + const auto intervalmax_max = + constant_interval_exprt(max_value, max_exprt(max_value.type())); + abstract_object_pointert op3 = std::make_shared( + intervalmax_max, enviroment, ns); + + bool modified; + abstract_object_pointert result = + abstract_objectt::meet(op1, op2, modified); + + const auto &cast_result = + std::dynamic_pointer_cast(result); + + THEN( + "A new constant abstract object set to intersection should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of meet + REQUIRE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE_FALSE(cast_result->is_bottom()); + + // Intersection should have this exact value + REQUIRE(cast_result->get_interval() == intervalmax_max); + } + } + WHEN( + "build constant AO with interval using gt_max_expression " + "then meet with a constant AO with the different interval") + { + abstract_object_pointert op1 = + std::make_shared(lt_10_x, enviroment, ns); + abstract_object_pointert op2 = + std::make_shared(x_gt_max, enviroment, ns); + + const auto &op2_cast = + std::dynamic_pointer_cast(op2); + REQUIRE(op2_cast->is_bottom()); + + const auto interval10_max = + constant_interval_exprt(val10, max_exprt(val10.type())); + + bool modified; + abstract_object_pointert result = + abstract_objectt::meet(op1, op2, modified); + + const auto &cast_result = + std::dynamic_pointer_cast(result); + + THEN( + "A new constant abstract object set to intersection should be returned") + { + // Though we may become top or bottom, the type should be unchanged + REQUIRE(cast_result); + + // Correctness of meet + REQUIRE(modified); + REQUIRE_FALSE(cast_result->is_top()); + REQUIRE(cast_result->is_bottom()); + } + } + } +} From 312465bf19e4891db558b9d93ffe5a011e8432d0 Mon Sep 17 00:00:00 2001 From: Petr Bauch Date: Mon, 10 Sep 2018 15:25:35 +0100 Subject: [PATCH 277/342] Added regression test for PR #295 --- regression/goto-analyzer/intervals_17/main.c | 17 +++++++++++++++++ regression/goto-analyzer/intervals_17/test.desc | 8 ++++++++ 2 files changed, 25 insertions(+) create mode 100644 regression/goto-analyzer/intervals_17/main.c create mode 100644 regression/goto-analyzer/intervals_17/test.desc diff --git a/regression/goto-analyzer/intervals_17/main.c b/regression/goto-analyzer/intervals_17/main.c new file mode 100644 index 00000000000..1f55b8559a3 --- /dev/null +++ b/regression/goto-analyzer/intervals_17/main.c @@ -0,0 +1,17 @@ + +int main() +{ + int x; + __CPROVER_assume(x >= 0); + __CPROVER_assume(x <= 10); + + int y; + __CPROVER_assume(y >= 5); + __CPROVER_assume(y <= 15); + + __CPROVER_assume(y < x); + + __CPROVER_assert(y <= 10, "y <= 10"); + + return 0; +} diff --git a/regression/goto-analyzer/intervals_17/test.desc b/regression/goto-analyzer/intervals_17/test.desc new file mode 100644 index 00000000000..49b26728533 --- /dev/null +++ b/regression/goto-analyzer/intervals_17/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--intervals --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main\.assertion\.1\] .* y\s*<=\s*10: Success$ +-- +^warning: ignoring From f73c94e03995dd6dfd1b82c73ae7c05699aa3a5c Mon Sep 17 00:00:00 2001 From: martin Date: Sun, 8 Dec 2019 11:44:10 +0000 Subject: [PATCH 278/342] Extend interval multiplication for extremes --- .../main.c | 7 +++++++ .../test.desc | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/main.c new file mode 100644 index 00000000000..3f2ed350f3e --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/main.c @@ -0,0 +1,7 @@ +extern int g_in; + +void main(void) +{ + int r = 4 * g_in; + int s = 0 * r; +} diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/test.desc new file mode 100644 index 00000000000..8a113f6e525 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/test.desc @@ -0,0 +1,7 @@ +CORE +main.c +--variable-sensitivity --interval-values --show +^EXIT=0$ +^SIGNAL=0$ +main::1::r \(\) -> TOP +main::1::s \(\) -> \[00000000000000000000000000000000, 00000000000000000000000000000000\] From 127c57c11201297988191f76e90bec963ce4d576 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 22 Aug 2018 15:29:26 +0100 Subject: [PATCH 279/342] Record data dependencies for functions with missing bodies --- .../goto-analyzer/dependence-graph16/main.c | 16 +++++++ .../dependence-graph16/test.desc | 10 +++++ .../test.desc | 10 +++++ .../variable_sensitivity_dependence_graph.cpp | 45 ++++++++++++++++++- 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 regression/goto-analyzer/dependence-graph16/main.c create mode 100644 regression/goto-analyzer/dependence-graph16/test.desc create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph16/test.desc diff --git a/regression/goto-analyzer/dependence-graph16/main.c b/regression/goto-analyzer/dependence-graph16/main.c new file mode 100644 index 00000000000..d4624824fab --- /dev/null +++ b/regression/goto-analyzer/dependence-graph16/main.c @@ -0,0 +1,16 @@ +int f2(int, const int*); +extern const int g_map[]; + +int g_out1; +int g_out2; + +extern int g_in; + +void main(void) +{ + int t1; + int t2; + + t1 = g_in; + t2 = f2(t1, g_map); +} diff --git a/regression/goto-analyzer/dependence-graph16/test.desc b/regression/goto-analyzer/dependence-graph16/test.desc new file mode 100644 index 00000000000..b866a8cb75d --- /dev/null +++ b/regression/goto-analyzer/dependence-graph16/test.desc @@ -0,0 +1,10 @@ +CORE +main.c +--dependence-graph --show +activate-multi-line-match +EXIT=0 +SIGNAL=0 +// Assignment from the result of a function call to a function with no body +// should have a data dependency on the function +^Data dependencies: 3 \[f2\]\n(.*\n).*\/\/ 4 file .*main.c line 15 function main\n.*t2 = NONDET\(signed int\); +-- diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph16/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph16/test.desc new file mode 100644 index 00000000000..ea7b68ebd01 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph16/test.desc @@ -0,0 +1,10 @@ +CORE +../dependence-graph16/main.c +--dependence-graph-vs --show +activate-multi-line-match +EXIT=0 +SIGNAL=0 +// Assignment from the result of a function call to a function with no body +// should have a data dependency on the function +^Data dependencies: 3 \[f2\]\n(.*\n).*\/\/ 4 file .*main.c line 15 function main\n.*t2 = NONDET\(signed int\); +-- diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index 36e594065f2..bbaa525c2c8 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -129,8 +129,51 @@ void variable_sensitivity_dependence_domaint::data_dependencies( if(to->is_assign()) { const code_assignt &inst = to_code_assign(to->code); + const exprt &rhs=inst.rhs(); - eval_data_deps(inst.rhs(), ns, domain_data_deps); + // Handle return value of a 'no body' function + if(rhs.id() == ID_side_effect) + { + const side_effect_exprt &see=to_side_effect_expr(rhs); + if(see.get_statement()==ID_nondet) + { + if(from->is_function_call()) + { + const code_function_callt &cfc=to_code_function_call(from->code); + const exprt &call=cfc.function(); + + if(call.id()==ID_symbol) + { + const irep_idt id=to_symbol_expr(call).id(); + const goto_functionst &goto_functions=dep_graph.goto_functions; + + goto_functionst::function_mapt::const_iterator it= + goto_functions.function_map.find(id); + + if(it!=goto_functions.function_map.end()) + { + if(!it->second.body_available()) // body not available + { + domain_data_deps[from].insert(call); + } + } + else // function not in map + { + domain_data_deps[from].insert(call); + } + } + else // complex call expression + { + domain_data_deps[from].insert(call); + } + } + } + } + else + { + // Just an ordinary assignement + eval_data_deps(rhs, ns, domain_data_deps); + } } else if (to->is_function_call()) { From 961958beec31563be241f657c091729376610b6c Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Wed, 22 Aug 2018 17:54:34 +0100 Subject: [PATCH 280/342] Avoid setting domain to TOP when calling functions with const pointer arguments --- .../variable-sensitivity-function-call/main.c | 20 +++++++++++++++++++ .../test.desc | 7 +++++++ .../variable_sensitivity_domain.cpp | 8 +++++--- 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 regression/goto-analyzer/variable-sensitivity-function-call/main.c create mode 100644 regression/goto-analyzer/variable-sensitivity-function-call/test.desc diff --git a/regression/goto-analyzer/variable-sensitivity-function-call/main.c b/regression/goto-analyzer/variable-sensitivity-function-call/main.c new file mode 100644 index 00000000000..604487528f2 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-function-call/main.c @@ -0,0 +1,20 @@ +int f(const int *y); + +extern const int g_map[]; + +int g_out1; +int g_out2; + +extern int g_in; +// int g_in; + +void main(void) +{ + int t1; + int t2; + + t1 = 5; + t2 = f(g_map); + + __CPROVER_assert(t1 == 5, "t1 == 5 after calling function with missing body"); +} diff --git a/regression/goto-analyzer/variable-sensitivity-function-call/test.desc b/regression/goto-analyzer/variable-sensitivity-function-call/test.desc new file mode 100644 index 00000000000..e847cd4bfa8 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-function-call/test.desc @@ -0,0 +1,7 @@ +CORE +main.c +--variable-sensitivity --verify +^EXIT=0$ +^SIGNAL=0$ +\[main.assertion.1\] file main.c line 19 function main, t1 == 5 after calling function with missing body: Success +-- diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 5048d00439d..f1cf9206966 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -425,11 +425,13 @@ void variable_sensitivity_domaint::transform_function_call( } else { - // For any parameter that is a pointer, top the value it is pointing - // at. + // For any parameter that is a non-const pointer, top the value it is + // pointing at. for(const exprt &called_arg : called_arguments) { - if(called_arg.type().id()==ID_pointer) + if( + called_arg.type().id() == ID_pointer && + !called_arg.type().subtype().get_bool(ID_C_constant)) { abstract_object_pointert pointer_value= abstract_state.eval(called_arg, ns); From 4d5b6764cbb71ccb1e49aed99c1b1566bfa40d80 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Fri, 24 Aug 2018 08:32:47 +0100 Subject: [PATCH 281/342] Merge when reading from array with unknown index. --- .../goto-analyzer/dependence-graph17/main.c | 23 ++++++++++++++++++ .../dependence-graph17/test.desc | 8 +++++++ .../test.desc | 8 +++++++ .../constant_array_abstract_object.cpp | 24 +++++++++++++++---- 4 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 regression/goto-analyzer/dependence-graph17/main.c create mode 100644 regression/goto-analyzer/dependence-graph17/test.desc create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc diff --git a/regression/goto-analyzer/dependence-graph17/main.c b/regression/goto-analyzer/dependence-graph17/main.c new file mode 100644 index 00000000000..d348399ec7a --- /dev/null +++ b/regression/goto-analyzer/dependence-graph17/main.c @@ -0,0 +1,23 @@ +extern int g_in; + +int g_a[3]; + +int g_out1; + +void main(void) +{ + int i; + + g_a[0] = 1; + g_a[1] = 2; + g_a[2] = 3; + + i = 0; + if (g_in > 0) + { + i=1; + g_a[2] = g_a[1]; + } + + g_out1 = g_a[i]; +} diff --git a/regression/goto-analyzer/dependence-graph17/test.desc b/regression/goto-analyzer/dependence-graph17/test.desc new file mode 100644 index 00000000000..df03f785b55 --- /dev/null +++ b/regression/goto-analyzer/dependence-graph17/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--dependence-graph --show +activate-multi-line-match +EXIT=0 +SIGNAL=0 +\*\*\*\* 9 file main\.c line 22 function main\nControl dependencies: 28 \[UNCONDITIONAL\]\nData dependencies: 1 \[g_a\[\(signed long int\)i\]\], 2 \[g_a\[\(signed long int\)i\]\], 3 \[g_a\[\(signed long int\)i\]\], 4 \[i\], 6 \[i\], 7 \[g_a\[\(signed long int\)i\]\] +-- diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc new file mode 100644 index 00000000000..8e8469d4d32 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc @@ -0,0 +1,8 @@ +CORE +../dependence-graph17/main.c +--dependence-graph-vs --arrays --show +activate-multi-line-match +EXIT=0 +SIGNAL=0 +\*\*\*\* 9 file main\.c line 22 function main\nControl dependencies: 28 \[UNCONDITIONAL\]\nData dependencies: 1 \[g_a\[\(signed long int\)i\]\], 2 \[g_a\[\(signed long int\)i\]\], 3 \[g_a\[\(signed long int\)i\]\], 4 \[i\], 6 \[i\], 7 \[g_a\[\(signed long int\)i\]\] +-- diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 860bc19a109..c09ed72b7bc 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -289,10 +289,26 @@ abstract_object_pointert constant_array_abstract_objectt::read_index( } 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); + // Although we don't know where we are reading from, and therefore + // we should be returning a TOP value, we may still have useful + // additional information in elements of the array - such as write + // histories so we merge all the known array elements with TOP and return + // that. + + // Create a new TOP value of the appropriate element type + abstract_object_pointert result = + env.abstract_object_factory(type().subtype(), ns, true, false); + + // Merge each known element into the TOP value + shared_array_mapt::viewt known_elements; + map.get_view(known_elements); + bool dummy; + for(const auto &element : known_elements) + { + result = abstract_objectt::merge(result, element.second, dummy); + } + + return result; } } } From f61fe5e9678c0d827da967cf5ab8dcbf3bb606ce Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Thu, 26 Apr 2018 12:43:11 +0100 Subject: [PATCH 282/342] Fixups post-rebase --- .../constant_assertions_01/test.desc | 10 +-- .../constant_assertions_02/test.desc | 10 +-- .../constant_propagation_10/test.desc | 2 +- .../constant_propagation_11/test.desc | 7 +- .../dependence-graph16/test.desc | 10 --- .../dependence-graph17/test.desc | 8 -- .../goto-analyzer/intervals_02/test.desc | 2 +- .../goto-analyzer/intervals_03/test.desc | 2 +- .../goto-analyzer/intervals_04/test.desc | 2 +- .../goto-analyzer/intervals_05/test.desc | 2 +- .../goto-analyzer/intervals_09/test.desc | 2 +- .../goto-analyzer/intervals_17/test.desc | 2 +- .../test.desc | 16 ++-- .../sensitivity-function-call-array/test.desc | 10 +-- .../test.desc | 8 +- .../test.desc | 10 +-- .../test.desc | 4 +- .../test.desc | 4 +- .../test.desc | 66 +++++++------- .../test.desc | 61 ++++++------- .../test.desc | 78 ++++++++--------- .../test.desc | 85 ++++++++++--------- .../test.desc | 4 +- .../test.desc | 10 +-- .../test.desc | 48 +++++------ .../test.desc | 28 +++--- .../unreachable_assertions_01/test.desc | 10 +-- .../test.desc | 12 +-- .../test.desc | 8 +- .../test.desc | 12 +-- .../test.desc | 18 ++-- .../test.desc | 10 +-- .../test.desc | 6 +- .../test.desc | 18 ++-- .../test.desc | 4 +- .../test.desc | 4 +- .../test.desc | 6 +- .../test.desc | 56 ++++++------ .../test.desc | 56 ++++++------ .../main.c | 23 +++++ .../test.desc | 2 +- .../main.c | 0 .../test.desc | 6 +- .../main.c | 0 .../test.desc | 8 +- .../test.desc | 8 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 6 +- .../test.desc | 10 ++- .../test.desc | 10 +-- .../test.desc | 4 +- .../test.desc | 4 +- .../test.desc | 4 +- .../test.desc | 12 +-- .../goto-analyzer/write-stack-types/test.desc | 2 +- .../abstract_enviroment.cpp | 46 +++++----- .../abstract_enviroment.h | 4 +- .../variable-sensitivity/abstract_object.cpp | 2 +- .../variable-sensitivity/abstract_object.h | 22 ++--- .../constant_array_abstract_object.cpp | 52 ++++++------ .../constant_array_abstract_object.h | 2 +- .../full_struct_abstract_object.cpp | 45 +++++----- .../full_struct_abstract_object.h | 2 +- .../interval_abstract_value.cpp | 6 +- .../interval_abstract_value.h | 2 +- .../interval_array_abstract_object.cpp | 3 +- .../variable_sensitivity_dependence_graph.cpp | 27 +++--- .../variable_sensitivity_dependence_graph.h | 15 ++-- .../variable_sensitivity_domain.cpp | 22 ++++- .../variable_sensitivity_domain.h | 4 +- .../variable-sensitivity/write_stack.cpp | 5 +- .../abstract_object/merge.cpp | 2 +- .../constant_abstract_value/merge.cpp | 3 +- .../constant_array_abstract_object/merge.cpp | 3 +- .../full_struct_abstract_object/merge.cpp | 3 +- .../interval_abstract_value/meet.cpp | 2 +- .../last_written_location.cpp | 3 +- .../variable-sensitivity/write_stack.cpp | 2 +- 81 files changed, 566 insertions(+), 529 deletions(-) delete mode 100644 regression/goto-analyzer/dependence-graph16/test.desc delete mode 100644 regression/goto-analyzer/dependence-graph17/test.desc create mode 100644 regression/goto-analyzer/variable-sensitivity-dependence-graph15/main.c rename regression/goto-analyzer/{dependence-graph16 => variable-sensitivity-dependence-graph16}/main.c (100%) rename regression/goto-analyzer/{dependence-graph17 => variable-sensitivity-dependence-graph17}/main.c (100%) diff --git a/regression/goto-analyzer/constant_assertions_01/test.desc b/regression/goto-analyzer/constant_assertions_01/test.desc index 51b45717a62..94fecb61f05 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 .* 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\)$ +^\[main.assertion.1\] line 10 0: FAILURE \(if reachable\)$ +^\[main.assertion.2\] line 11 0 && 1: FAILURE \(if reachable\)$ +^\[main.assertion.3\] line 12 0 || 0: FAILURE \(if reachable\)$ +^\[main.assertion.4\] line 13 0 && x: FAILURE \(if reachable\)$ +^\[main.assertion.5\] line 14 y && 0: FAILURE \(if reachable\)$ ^EXIT=0$ ^SIGNAL=0$ -- diff --git a/regression/goto-analyzer/constant_assertions_02/test.desc b/regression/goto-analyzer/constant_assertions_02/test.desc index 577ec981fd2..8f7f77cfc7f 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 .* 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 +^\[main\.assertion\.1\] line 10 1: SUCCESS +^\[main\.assertion\.2\] line 11 0 || 1: SUCCESS +^\[main\.assertion\.3\] line 12 1 && 1: SUCCESS +^\[main\.assertion\.4\] line 13 1 || x: SUCCESS +^\[main\.assertion\.5\] line 14 y || 1: SUCCESS ^EXIT=0$ ^SIGNAL=0$ -- diff --git a/regression/goto-analyzer/constant_propagation_10/test.desc b/regression/goto-analyzer/constant_propagation_10/test.desc index 43d07eb8172..fcc7a098b29 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\] .* a\[0\]==2: Failure \(if reachable\)$ +^\[main\.assertion\.1\] line 10 a\[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 4bc8b249535..2c21db37186 100644 --- a/regression/goto-analyzer/constant_propagation_11/test.desc +++ b/regression/goto-analyzer/constant_propagation_11/test.desc @@ -1,10 +1,9 @@ CORE main.c ---variable --arrays --verify +--variable --arrays --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 1: SUCCESS$ -^Simplified: assert: 1, assume: 0, goto: 1, assigns: 6, function calls: 0$ -^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 9, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 7, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 12, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/dependence-graph16/test.desc b/regression/goto-analyzer/dependence-graph16/test.desc deleted file mode 100644 index b866a8cb75d..00000000000 --- a/regression/goto-analyzer/dependence-graph16/test.desc +++ /dev/null @@ -1,10 +0,0 @@ -CORE -main.c ---dependence-graph --show -activate-multi-line-match -EXIT=0 -SIGNAL=0 -// Assignment from the result of a function call to a function with no body -// should have a data dependency on the function -^Data dependencies: 3 \[f2\]\n(.*\n).*\/\/ 4 file .*main.c line 15 function main\n.*t2 = NONDET\(signed int\); --- diff --git a/regression/goto-analyzer/dependence-graph17/test.desc b/regression/goto-analyzer/dependence-graph17/test.desc deleted file mode 100644 index df03f785b55..00000000000 --- a/regression/goto-analyzer/dependence-graph17/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -CORE -main.c ---dependence-graph --show -activate-multi-line-match -EXIT=0 -SIGNAL=0 -\*\*\*\* 9 file main\.c line 22 function main\nControl dependencies: 28 \[UNCONDITIONAL\]\nData dependencies: 1 \[g_a\[\(signed long int\)i\]\], 2 \[g_a\[\(signed long int\)i\]\], 3 \[g_a\[\(signed long int\)i\]\], 4 \[i\], 6 \[i\], 7 \[g_a\[\(signed long int\)i\]\] --- diff --git a/regression/goto-analyzer/intervals_02/test.desc b/regression/goto-analyzer/intervals_02/test.desc index e518380684b..480d556bd35 100644 --- a/regression/goto-analyzer/intervals_02/test.desc +++ b/regression/goto-analyzer/intervals_02/test.desc @@ -3,6 +3,6 @@ main.c --intervals ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 5 assertion x > -10 \&\& x < 100: SUCCESS$ +^\[main.assertion.1\] line 5 x > -10 \&\& x < 100: SUCCESS$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/intervals_03/test.desc b/regression/goto-analyzer/intervals_03/test.desc index 00726fdd6f0..f5fc98f9f56 100644 --- a/regression/goto-analyzer/intervals_03/test.desc +++ b/regression/goto-analyzer/intervals_03/test.desc @@ -3,6 +3,6 @@ main.c --intervals ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 6 assertion x > -10 \|\| x < 100: SUCCESS$ +^\[main.assertion.1\] line 6 x > -10 \|\| x < 100: SUCCESS$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/intervals_04/test.desc b/regression/goto-analyzer/intervals_04/test.desc index f34e816cf39..b612277f1bd 100644 --- a/regression/goto-analyzer/intervals_04/test.desc +++ b/regression/goto-analyzer/intervals_04/test.desc @@ -3,6 +3,6 @@ main.c --intervals ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 8 assertion i >= 1 && i <= 2: SUCCESS$ +^\[main.assertion.1\] line 8 i>=1 && i<=2: SUCCESS$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/intervals_05/test.desc b/regression/goto-analyzer/intervals_05/test.desc index 0d3af8f5307..d75c1c9243e 100644 --- a/regression/goto-analyzer/intervals_05/test.desc +++ b/regression/goto-analyzer/intervals_05/test.desc @@ -3,6 +3,6 @@ main.c --intervals ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 8 assertion i >= 1 \|\| i <= 2: SUCCESS$ +^\[main.assertion.1\] line 8 i>=1 \|\| i<=2: SUCCESS$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/intervals_09/test.desc b/regression/goto-analyzer/intervals_09/test.desc index d9a544fef3b..60d294f9c2c 100644 --- a/regression/goto-analyzer/intervals_09/test.desc +++ b/regression/goto-analyzer/intervals_09/test.desc @@ -3,6 +3,6 @@ main.c --intervals ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 8 assertion i >= 1 \&\& i <= 2: SUCCESS$ +^\[main.assertion.1\] line 8 i>=1 \&\& i<=2: SUCCESS$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/intervals_17/test.desc b/regression/goto-analyzer/intervals_17/test.desc index 49b26728533..cecc1cc3321 100644 --- a/regression/goto-analyzer/intervals_17/test.desc +++ b/regression/goto-analyzer/intervals_17/test.desc @@ -3,6 +3,6 @@ main.c --intervals --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] .* y\s*<=\s*10: Success$ +^\[main\.assertion\.1\] line 14 y <= 10: SUCCESS$ -- ^warning: ignoring 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 48983ce22d7..8b39662488f 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\] .* 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$ +^\[main.assertion.1\] line 13 x.a==0: SUCCESS$ +^\[main.assertion.2\] line 14 x.a==1: FAILURE \(if reachable\)$ +^\[main.assertion.3\] line 18 x.a==0: SUCCESS$ +^\[main.assertion.4\] line 19 x.a==1: FAILURE \(if reachable\)$ +^\[main.assertion.5\] line 21 x.a==0: FAILURE \(if reachable\)$ +^\[main.assertion.6\] line 22 x.a==1: SUCCESS$ +^\[main.assertion.7\] line 24 x.a==0: UNKNOWN$ +^\[main.assertion.8\] line 25 x.a==1: UNKNOWN$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-function-call-array/test.desc b/regression/goto-analyzer/sensitivity-function-call-array/test.desc index 14a8c38bb3a..a18b9d26b11 100644 --- a/regression/goto-analyzer/sensitivity-function-call-array/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-array/test.desc @@ -3,10 +3,10 @@ main.c --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] .* assertion \*arr_y==2: Success$ -^\[main\.assertion\.2\] .* assertion p2arr==arr_y: Success$ -^\[main\.assertion\.3\] .* assertion \*p2arr==2: Success$ -^\[bar\.assertion\.1\] .* assertion \*arr_unmodified==1: Success$ -^\[bar\.assertion\.2\] .* assertion \*arr_modified==2: Success$ +^\[main\.assertion\.1\] line 12 assertion \*arr_y==2: SUCCESS$ +^\[main\.assertion\.2\] line 15 assertion p2arr==arr_y: SUCCESS$ +^\[main\.assertion\.3\] line 16 assertion \*p2arr==2: SUCCESS$ +^\[bar\.assertion\.1\] line 22 assertion \*arr_unmodified==1: SUCCESS$ +^\[bar\.assertion\.2\] line 28 assertion \*arr_modified==2: SUCCESS$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc b/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc index 5302bc865d5..fc6ff19a7e2 100644 --- a/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc @@ -3,9 +3,9 @@ main.c --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] file main.c .* assertion x==3: Success$ -^\[main\.assertion\.2\] file main.c .* assertion y==4: Unknown$ -^\[main\.assertion\.3\] file main.c .* assertion z==0: Unknown$ -^\[main\.assertion\.4\] file main.c .* assertion global_value==4: Unknown$ +^\[main\.assertion\.1\] line 16 assertion x==3: SUCCESS$ +^\[main\.assertion\.2\] line 17 assertion y==4: UNKNOWN$ +^\[main\.assertion\.3\] line 18 assertion z==0: UNKNOWN$ +^\[main\.assertion\.4\] line 19 assertion global_value==4: UNKNOWN$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc b/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc index 7789cbb03da..3f51c709a16 100644 --- a/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc @@ -3,10 +3,10 @@ main.c --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] .* assertion y==5: Success$ -^\[main\.assertion\.2\] .* assertion p2x==&y: Success$ -^\[main\.assertion\.3\] .* assertion \*p2x==5: Success$ -^\[bar\.assertion\.1\] .* assertion \*unmodified==3: Success$ -^\[bar\.assertion\.2\] .* assertion \*modifed==5: Success$ +^\[main\.assertion\.1\] line 11 assertion y==5: SUCCESS$ +^\[main\.assertion\.2\] line 12 assertion p2x==&y: SUCCESS$ +^\[main\.assertion\.3\] line 13 assertion \*p2x==5: SUCCESS$ +^\[bar\.assertion\.1\] line 18 assertion \*unmodified==3: SUCCESS$ +^\[bar\.assertion\.2\] line 22 assertion \*modifed==5: SUCCESS$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc b/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc index 18e4cd5fc0e..f96f9fd17ed 100644 --- a/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc @@ -3,7 +3,7 @@ main.c --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[bar\.assertion\.1\] .* assertion other==4: Success$ -^\[main\.assertion\.1\] .* assertion y==5: Success$ +^\[bar\.assertion\.1\] line 5 assertion other==4: SUCCESS$ +^\[main\.assertion\.1\] line 13 assertion y==5: SUCCESS$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc b/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc index c75fb1d3837..ed8255be9f7 100644 --- a/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc @@ -3,7 +3,7 @@ main.c --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] .* assertion y==6: Unknown$ -^\[main\.assertion\.2\] .* assertion z==0: Unknown$ +^\[main\.assertion\.1\] line 22 assertion y==6: UNKNOWN$ +^\[main\.assertion\.2\] line 25 assertion z==0: UNKNOWN$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc index f753d144dae..3602b0c9757 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc @@ -3,38 +3,36 @@ sensitivity_dependency_arrays.c --variable --arrays --pointers --structs --show // Enable multi-line checking activate-multi-line-match -__CPROVER_threads_exited \(\) -> TOP @ \[14\] -__CPROVER_malloc_is_new_array \(\) -> false @ \[6\] -__CPROVER_dead_object \(\) -> TOP @ \[4\] -__CPROVER_deallocated \(\) -> TOP @ \[5\] -__CPROVER_malloc_object \(\) -> TOP @ \[7\] -__CPROVER_memory_leak \(\) -> TOP @ \[9\] -__CPROVER_rounding_mode \(\) -> 00000000000000000000000000000000 @ \[12\] -__CPROVER_pipe_count \(\) -> 00000000000000000000000000000000 @ \[11\] -__CPROVER_malloc_size \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[8\] -__CPROVER_next_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[10\] -__CPROVER_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[13\] +^EXIT=0$ +^SIGNAL=0$ main#return_value \(\) -> TOP @ \[1\] -do_arrays::1::bool_ \(\) -> TOP @ \[16\] -do_arrays::1::bool_1 \(\) -> TOP @ \[17\] -do_arrays::1::bool_2 \(\) -> TOP @ \[18\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000011110 @ \[22\]\n\[1\] = 00000000000000000000000000010100 @ \[21\]\n\} @ \[22\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000011110 @ \[22\]\n\[1\] = 00000000000000000000000000101000 @ \[23\]\n\} @ \[23\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000011110 @ \[22\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n\} @ \[24\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000011110 @ \[25\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n\} @ \[25\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000000101 @ \[26\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n\} @ \[26\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000011110 @ \[24\]\n\} @ \[27\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[28\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[28\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000010100 @ \[30\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[30\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000001111 @ \[27\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[28\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000010100 @ \[30\, 32\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[30\, 32\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000000000 @ \[34\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[34\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000000011 @ \[36\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[36\] -do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[36\, 38\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[36\, 38\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000000000 @ \[34\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[34\] -do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[36\, 38\, 41\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[36\, 38\, 41\] -do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[36\, 38\, 41\]\n\[1\] = 00000000000000000000000000001010 @ \[28\]\n\} @ \[36\, 38\, 41\] -do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[36\, 38\, 41\]\n\[1\] = 00000000000000000000000000001010 @ \[43\]\n\} @ \[43\] -do_arrays::1::x \(\) -> \{\[0\] = 00000000000000000000000000010100 @ \[44\]\n\[1\] = 00000000000000000000000000001010 @ \[43\]\n\} @ \[44\] --- +__CPROVER_dead_object \(\) -> TOP @ \[5\] +__CPROVER_deallocated \(\) -> TOP @ \[6\] +__CPROVER_malloc_is_new_array \(\) -> false @ \[7\] +__CPROVER_malloc_object \(\) -> TOP @ \[8\] +__CPROVER_malloc_size \(\) -> 0 @ \[9\] +__CPROVER_memory_leak \(\) -> TOP @ \[10\] +__CPROVER_next_thread_id \(\) -> 0 @ \[11\] +__CPROVER_pipe_count \(\) -> 0 @ \[13\] +__CPROVER_rounding_mode \(\) -> 0 @ \[14\] +__CPROVER_thread_id \(\) -> 0 @ \[15\] +__CPROVER_threads_exited \(\) -> TOP @ \[18\] +do_arrays::1::bool_ \(\) -> TOP @ \[20\] +do_arrays::1::bool_1 \(\) -> TOP @ \[21\] +do_arrays::1::bool_2 \(\) -> TOP @ \[22\] +do_arrays::1::x \(\) -> \{\[0\] = A @ \[24\]\n\} @ \[24\] +do_arrays::1::x \(\) -> \{\[0\] = A @ \[24\]\n\[1\] = 14 @ \[25\]\n\} @ \[25\] +do_arrays::1::x \(\) -> \{\[0\] = 1E @ \[26\]\n\[1\] = 14 @ \[25\]\n\} @ \[26\] +do_arrays::1::x \(\) -> \{\[0\] = 1E @ \[26\]\n\[1\] = 28 @ \[27\]\n\} @ \[27\] +do_arrays::1::x \(\) -> \{\[0\] = 1E @ \[26\]\n\[1\] = 1E @ \[28\]\n\} @ \[28\] +do_arrays::1::x \(\) -> \{\[0\] = 1E @ \[29\]\n\[1\] = 1E @ \[28\]\n\} @ \[29\] +do_arrays::1::x \(\) -> \{\[0\] = 5 @ \[30\]\n\[1\] = 1E @ \[28\]\n\} @ \[30\] +do_arrays::1::x \(\) -> \{\[0\] = F @ \[31\]\n\[1\] = 1E @ \[28\]\n\} @ \[31\] +do_arrays::1::x \(\) -> \{\[0\] = F @ \[31\]\n\[1\] = A @ \[32\]\n\} @ \[32\] +do_arrays::1::x \(\) -> \{\[0\] = 14 @ \[34\]\n\[1\] = A @ \[32\]\n\} @ \[34\] +do_arrays::1::x \(\) -> \{\[0\] = 14 @ \[34\, 36\]\n\[1\] = A @ \[32\]\n\} @ \[34\, 36\] +do_arrays::1::x \(\) -> \{\[0\] = 0 @ \[38]\n\[1\] = A @ \[32\]\n\} @ \[38\] +do_arrays::1::x \(\) -> \{\[0\] = 3 @ \[40]\n\[1\] = A @ \[32\]\n\} @ \[40\] +do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[40\, 42]\n\[1\] = A @ \[32\]\n\} @ \[40\, 42\] +do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[40\, 42\, 45]\n\[1\] = A @ \[47\]\n\} @ \[47\] +do_arrays::1::x \(\) -> \{\[0\] = 14 @ \[48]\n\[1\] = A @ \[47\]\n\} @ \[48\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc index e18e4451968..bb4e745e672 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc @@ -3,34 +3,35 @@ sensitivity_dependency_pointers.c --variable --arrays --pointers --structs --show // Enable multi-line checking activate-multi-line-match -__CPROVER_threads_exited \(\) -> TOP @ \[14\] -__CPROVER_malloc_is_new_array \(\) -> false @ \[6\] -__CPROVER_dead_object \(\) -> TOP @ \[4\] -__CPROVER_deallocated \(\) -> TOP @ \[5\] -__CPROVER_malloc_object \(\) -> TOP @ \[7\] -__CPROVER_memory_leak \(\) -> TOP @ \[9\] -__CPROVER_rounding_mode \(\) -> 00000000000000000000000000000000 @ \[12\] -__CPROVER_pipe_count \(\) -> 00000000000000000000000000000000 @ \[11\] -__CPROVER_malloc_size \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[8\] -__CPROVER_next_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[10\] -__CPROVER_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[13\] +^EXIT=0$ +^SIGNAL=0$ main#return_value \(\) -> TOP @ \[1\] -do_pointers::1::bool_ \(\) -> TOP @ \[16\] -do_pointers::1::bool_1 \(\) -> TOP @ \[17\] -do_pointers::1::bool_2 \(\) -> TOP @ \[18\] -do_pointers::1::x \(\) -> TOP @ \[19\] -do_pointers::1::x \(\) -> 00000000000000000000000000001010 @ \[20\] -do_pointers::1::x_p \(\) -> TOP @ \[21\] -do_pointers::1::y \(\) -> TOP @ \[22\] -do_pointers::1::y \(\) -> 00000000000000000000000000010100 @ \[23\] -do_pointers::1::y_p \(\) -> TOP @ \[24\] -do_pointers::1::x_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[25\] -do_pointers::1::x \(\) -> 00000000000000000000000000011110 @ \[26\] -do_pointers::1::x \(\) -> 00000000000000000000000000101000 @ \[27\] -do_pointers::1::x \(\) -> TOP @ \[28\] -do_pointers::1::x \(\) -> 00000000000000000000000000110010 @ \[29\] -do_pointers::1::y_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[30\] -do_pointers::1::x \(\) -> 00000000000000000000000000111100 @ \[31\] -do_pointers::1::j \(\) -> TOP @ \[32\] -do_pointers::1::j \(\) -> 00000000000000000000000000111100 @ \[33\] --- +__CPROVER_dead_object \(\) -> TOP @ \[5\] +__CPROVER_deallocated \(\) -> TOP @ \[6\] +__CPROVER_malloc_is_new_array \(\) -> false @ \[7\] +__CPROVER_malloc_object \(\) -> TOP @ \[8\] +__CPROVER_malloc_size \(\) -> 0 @ \[9\] +__CPROVER_memory_leak \(\) -> TOP @ \[10\] +__CPROVER_next_thread_id \(\) -> 0 @ \[11\] +__CPROVER_pipe_count \(\) -> 0 @ \[13\] +__CPROVER_rounding_mode \(\) -> 0 @ \[14\] +__CPROVER_thread_id \(\) -> 0 @ \[15\] +__CPROVER_threads_exited \(\) -> TOP @ \[18\] +do_pointers::1::bool_ \(\) -> TOP @ \[20\] +do_pointers::1::bool_1 \(\) -> TOP @ \[21\] +do_pointers::1::bool_2 \(\) -> TOP @ \[22\] +do_pointers::1::x \(\) -> TOP @ \[23\] +do_pointers::1::x \(\) -> A @ \[24\] +do_pointers::1::x_p \(\) -> TOP @ \[25\] +do_pointers::1::y \(\) -> TOP @ \[26\] +do_pointers::1::y \(\) -> 14 @ \[27\] +do_pointers::1::y_p \(\) -> TOP @ \[28\] +do_pointers::1::x_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[29\] +do_pointers::1::x \(\) -> 1E @ \[30\] +do_pointers::1::x \(\) -> 28 @ \[31\] +do_pointers::1::x \(\) -> TOP @ \[32\] +do_pointers::1::x \(\) -> 32 @ \[33\] +do_pointers::1::y_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[34\] +do_pointers::1::x \(\) -> 3C @ \[35\] +do_pointers::1::j \(\) -> TOP @ \[36\] +do_pointers::1::j \(\) -> 3C @ \[37\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc index e4df2d1d3a6..6a8dd629c79 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc @@ -3,47 +3,41 @@ sensitivity_dependency_structs.c --variable --arrays --pointers --structs --show // Enable multi-line checking activate-multi-line-match -__CPROVER_threads_exited \(\) -> TOP @ \[14\] -__CPROVER_malloc_is_new_array \(\) -> false @ \[6\] -__CPROVER_dead_object \(\) -> TOP @ \[4\] -__CPROVER_deallocated \(\) -> TOP @ \[5\] -__CPROVER_malloc_object \(\) -> TOP @ \[7\] -__CPROVER_memory_leak \(\) -> TOP @ \[9\] -__CPROVER_rounding_mode \(\) -> 00000000000000000000000000000000 @ \[12\] -__CPROVER_pipe_count \(\) -> 00000000000000000000000000000000 @ \[11\] -__CPROVER_malloc_size \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[8\] -__CPROVER_next_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[10\] -__CPROVER_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[13\] +^EXIT=0$ +^SIGNAL=0$ main#return_value \(\) -> TOP @ \[1\] -do_structs::1::bool_ \(\) -> TOP @ \[16\] -do_structs::1::bool_1 \(\) -> TOP @ \[17\] -do_structs::1::bool_2 \(\) -> TOP @ \[18\] -do_structs::1::st \(\) -> \{\} @ \[19\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000001010 @ \[20\]\} @ \[20\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000001010 @ \[20\]\, .y=00000000000000000000000000010100 @ \[21\]\} @ \[21\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000011110 @ \[22\]\, .y=00000000000000000000000000010100 @ \[21\]\} @ \[22\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000011110 @ \[22\]\, .y=00000000000000000000000000101000 @ \[23\]\} @ \[23\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000011110 @ \[22\]\, .y=00000000000000000000000000011110 @ \[24\]\} @ \[24\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000011110 @ \[25\]\, .y=00000000000000000000000000011110 @ \[24\]\} @ \[25\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000000101 @ \[26\]\, .y=00000000000000000000000000011110 @ \[24\]\} @ \[26\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000011110 @ \[24\]\} @ \[27\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[28\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[28\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000010100 @ \[30\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[30\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000001111 @ \[27\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[28\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000010100 @ \[30\, 32\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[30\, 32\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000010100 @ \[30\, 32\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[30\, 32\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000000000 @ \[34\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[34\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000000000 @ \[34\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[34\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000000011 @ \[36\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[36\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000000011 @ \[36\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[36\] -do_structs::1::st \(\) -> \{.x=TOP @ \[36\, 38\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[36\, 38\] -do_structs::1::st \(\) -> \{.x=TOP @ \[36\, 38\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[36\, 38\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000000000 @ \[34\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[34\] -do_structs::1::st \(\) -> \{.x=TOP @ \[36\, 38\, 41\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[36\, 38\, 41\] -do_structs::1::st \(\) -> \{.x=TOP @ \[36\, 38\, 41\]\, .y=00000000000000000000000000001010 @ \[28\]\} @ \[36\, 38\, 41\] -do_structs::1::st \(\) -> \{.x=TOP @ \[36\, 38\, 41\]\, .y=00000000000000000000000000001010 @ \[43\]\} @ \[43\] -do_structs::1::st \(\) -> \{.x=00000000000000000000000000010100 @ \[44\]\, .y=00000000000000000000000000001010 @ \[43\]\} @ \[44\] -do_structs::1::new_age \(\) -> \{\} @ \[45\] -do_structs::1::new_age \(\) -> \{.x=00000000000000000000000000010100 @ \[46\]\, .y=00000000000000000000000000001010 @ \[46\]\} @ \[46\] +__CPROVER_dead_object \(\) -> TOP @ \[5\] +__CPROVER_deallocated \(\) -> TOP @ \[6\] +__CPROVER_malloc_is_new_array \(\) -> false @ \[7\] +__CPROVER_malloc_object \(\) -> TOP @ \[8\] +__CPROVER_malloc_size \(\) -> 0 @ \[9\] +__CPROVER_memory_leak \(\) -> TOP @ \[10\] +__CPROVER_next_thread_id \(\) -> 0 @ \[11\] +__CPROVER_pipe_count \(\) -> 0 @ \[13\] +__CPROVER_rounding_mode \(\) -> 0 @ \[14\] +__CPROVER_thread_id \(\) -> 0 @ \[15\] +__CPROVER_threads_exited \(\) -> TOP @ \[18\] +do_structs::1::bool_ \(\) -> TOP @ \[20\] +do_structs::1::bool_1 \(\) -> TOP @ \[21\] +do_structs::1::bool_2 \(\) -> TOP @ \[22\] +do_structs::1::st \(\) -> \{\} @ \[23\] +do_structs::1::st \(\) -> \{.x=A @ \[24\]\} @ \[24\] +do_structs::1::st \(\) -> \{.x=A @ \[24\]\, .y=14 @ \[25\]\} @ \[25\] +do_structs::1::st \(\) -> \{.x=1E @ \[26\]\, .y=14 @ \[25\]\} @ \[26\] +do_structs::1::st \(\) -> \{.x=1E @ \[26\]\, .y=28 @ \[27\]\} @ \[27\] +do_structs::1::st \(\) -> \{.x=1E @ \[26\]\, .y=1E @ \[28\]\} @ \[28\] +do_structs::1::st \(\) -> \{.x=1E @ \[29\]\, .y=1E @ \[28\]\} @ \[29\] +do_structs::1::st \(\) -> \{.x=5 @ \[30\]\, .y=1E @ \[28\]\} @ \[30\] +do_structs::1::st \(\) -> \{.x=F @ \[31\]\, .y=1E @ \[28\]\} @ \[31\] +do_structs::1::st \(\) -> \{.x=F @ \[31\]\, .y=A @ \[32\]\} @ \[32\] +do_structs::1::st \(\) -> \{.x=14 @ \[34\]\, .y=A @ \[32\]\} @ \[34\] +do_structs::1::st \(\) -> \{.x=14 @ \[34\, 36\]\, .y=A @ \[32\]\} @ \[34\, 36\] +do_structs::1::st \(\) -> \{.x=0 @ \[38\]\, .y=A @ \[32\]\} @ \[38\] +do_structs::1::st \(\) -> \{.x=3 @ \[40\]\, .y=A @ \[32\]\} @ \[40\] +do_structs::1::st \(\) -> \{.x=TOP @ \[40\, 42\]\, .y=A @ \[32\]\} @ \[40\, 42\] +do_structs::1::st \(\) -> \{.x=TOP @ \[40\, 42\, 45\]\, .y=A @ \[32\]\} @ \[40\, 42\, 45\] +do_structs::1::st \(\) -> \{.x=TOP @ \[40\, 42\, 45\]\, .y=A @ \[47\]\} @ \[47\] +do_structs::1::st \(\) -> \{.x=14 @ \[48\]\, .y=A @ \[47\]\} @ \[48\] +do_structs::1::new_age \(\) -> \{\} @ \[49\] +do_structs::1::new_age \(\) -> \{.x=14 @ \[50\]\, .y=A @ \[50\]\} @ \[50\] -- diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc index 24b62b9191a..c8141e00d9c 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc @@ -1,46 +1,49 @@ CORE sensitivity_dependency_variables.c --variable --arrays --pointers --structs --show -// Enable multi-line checking -activate-multi-line-match -__CPROVER_threads_exited \(\) -> TOP @ \[14\] -__CPROVER_malloc_is_new_array \(\) -> false @ \[6\] -__CPROVER_dead_object \(\) -> TOP @ \[4\] -__CPROVER_deallocated \(\) -> TOP @ \[5\] -__CPROVER_malloc_object \(\) -> TOP @ \[7\] -__CPROVER_memory_leak \(\) -> TOP @ \[9\] -__CPROVER_rounding_mode \(\) -> 00000000000000000000000000000000 @ \[12\] -global_x \(\) -> 00000000000000000000000000000000 @ \[15\] -__CPROVER_pipe_count \(\) -> 00000000000000000000000000000000 @ \[11\] -__CPROVER_malloc_size \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[8\] -__CPROVER_next_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[10\] -__CPROVER_thread_id \(\) -> 0000000000000000000000000000000000000000000000000000000000000000 @ \[13\] +^EXIT=0$ +^SIGNAL=0$ main#return_value \(\) -> TOP @ \[1\] -do_variables::1::bool_ \(\) -> TOP @ \[17\] -do_variables::1::bool_1 \(\) -> TOP @ \[18\] -do_variables::1::bool_2 \(\) -> TOP @ \[19\] -do_variables::1::x \(\) -> TOP @ \[21\] -global_x \(\) -> 00000000000000000000000000000101 @ \[20\] -do_variables::1::x \(\) -> 00000000000000000000000000001010 @ \[22\] -do_variables::1::y \(\) -> TOP @ \[23\] -do_variables::1::y \(\) -> 00000000000000000000000000010100 @ \[24\] -do_variables::1::x \(\) -> 00000000000000000000000000011110 @ \[25\] -do_variables::1::y \(\) -> 00000000000000000000000000101000 @ \[26\] -do_variables::1::y \(\) -> 00000000000000000000000000011110 @ \[27\] -do_variables::1::x \(\) -> 00000000000000000000000000011110 @ \[28\] -do_variables::1::x \(\) -> 00000000000000000000000000000101 @ \[29\] -do_variables::1::x \(\) -> 00000000000000000000000000001111 @ \[30\] -do_variables::1::y \(\) -> 00000000000000000000000000001010 @ \[31\] -do_variables::1::x \(\) -> 00000000000000000000000000010100 @ \[33\] -do_variables::1::x \(\) -> 00000000000000000000000000010100 @ \[33\, 35\] -do_variables::1::x \(\) -> 00000000000000000000000000010100 @ \[33\, 35\] -do_variables::1::x \(\) -> 00000000000000000000000000110010 @ \[37\] -do_variables::1::x \(\) -> 00000000000000000000000000010100 @ \[39\] -do_variables::1::x \(\) -> TOP @ \[39\, 41\] -do_variables::1::x \(\) -> 00000000000000000000000000000000 @ \[43\] -do_variables::1::x \(\) -> 00000000000000000000000000000011 @ \[45\] -do_variables::1::x \(\) -> TOP @ \[45\, 47\] -do_variables::1::x \(\) -> TOP @ \[45\, 47\, 50\] -do_variables::1::y \(\) -> 00000000000000000000000000001010 @ \[52\] -do_variables::1::x \(\) -> 00000000000000000000000000010100 @ \[53\] +__CPROVER_alloca_object \(\) -> TOP @ \[4\] +__CPROVER_dead_object \(\) -> TOP @ \[5\] +__CPROVER_deallocated \(\) -> TOP @ \[6\] +__CPROVER_malloc_is_new_array \(\) -> false @ \[7\] +__CPROVER_malloc_object \(\) -> TOP @ \[8\] +__CPROVER_malloc_size \(\) -> 0 @ \[9\] +__CPROVER_memory_leak \(\) -> TOP @ \[10\] +__CPROVER_next_thread_id \(\) -> 0 @ \[11\] +__CPROVER_next_thread_key \(\) -> 0 @ \[12\] +__CPROVER_pipe_count \(\) -> 0 @ \[13\] +__CPROVER_rounding_mode \(\) -> 0 @ \[14\] +__CPROVER_thread_id \(\) -> 0 @ \[15\] +__CPROVER_thread_key_dtors \(\) -> TOP @ \[16\] +__CPROVER_thread_keys \(\) -> TOP @ \[17\] +__CPROVER_threads_exited \(\) -> TOP @ \[18\] +global_x \(\) -> 0 @ \[19\] +do_variables::1::bool_ \(\) -> TOP @ \[21\] +do_variables::1::bool_1 \(\) -> TOP @ \[22\] +do_variables::1::bool_2 \(\) -> TOP @ \[23\] +global_x \(\) -> 5 @ \[24\] +do_variables::1::x \(\) -> TOP @ \[25\] +do_variables::1::x \(\) -> A @ \[26\] +do_variables::1::y \(\) -> TOP @ \[27\] +do_variables::1::y \(\) -> 14 @ \[28\] +do_variables::1::x \(\) -> 1E @ \[29\] +do_variables::1::y \(\) -> 28 @ \[30\] +do_variables::1::y \(\) -> 1E @ \[31\] +do_variables::1::x \(\) -> 1E @ \[32\] +do_variables::1::x \(\) -> 5 @ \[33\] +do_variables::1::x \(\) -> F @ \[34\] +do_variables::1::y \(\) -> A @ \[35\] +do_variables::1::x \(\) -> 14 @ \[37\] +do_variables::1::x \(\) -> 14 @ \[37\, 39\] +do_variables::1::x \(\) -> 32 @ \[41\] +do_variables::1::x \(\) -> 14 @ \[43\] +do_variables::1::x \(\) -> TOP @ \[43\, 45\] +do_variables::1::x \(\) -> 0 @ \[47\] +do_variables::1::x \(\) -> 3 @ \[49\] +do_variables::1::x \(\) -> TOP @ \[49\, 51\] +do_variables::1::x \(\) -> TOP @ \[49\, 51\, 54\] +do_variables::1::y \(\) -> A @ \[56\] +do_variables::1::x \(\) -> 14 @ \[57\] -- diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc index 37736c7bba5..34f32f40a5d 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc @@ -3,7 +3,7 @@ main.c --variable --arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* array\[0\] == 5: Unknown$ -^\[main.assertion.2\] .* array\[1\] == 5: Unknown$ +^\[main.assertion.1\] line 11 array\[0\] == 5: UNKNOWN$ +^\[main.assertion.2\] line 12 array\[1\] == 5: UNKNOWN$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc b/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc index 9ebe48039a5..9018d894ea3 100644 --- a/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc +++ b/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc @@ -3,10 +3,10 @@ data-dependency-context.c --variable --structs --arrays --data-dependencies --show // Enable multi-line checking activate-multi-line-match -EXIT=0 -SIGNAL=0 -st \(\) -> \{.a=.* @ \[2, 47\]\[Data dependencies: 47, 2\]\[Data dominators: \], .b=.* @ \[5, 47\]\[Data dependencies: 47, 5\]\[Data dominators: \]\} @ \[2, 5, 47\]\[Data dependencies: 47, 5, 2\]\[Data dominators: 47\] -ar \(\) -> \{\[0\] = .* @ \[11, 42\]\[Data dependencies: 42, 11\]\[Data dominators: \]\n\[1\] = .* @ \[14, 42\]\[Data dependencies: 42, 14\]\[Data dominators: \]\n\} @ \[11, 14, 42\]\[Data dependencies: 42, 14, 11\]\[Data dominators: 42\] -arr \(\) -> \{\[0\] = .* @ \[19\]\[Data dependencies: 19\]\[Data dominators: 19\]\n\[1\] = .* @ \[20\]\[Data dependencies: 20\]\[Data dominators: 20\]\n\[2\] = .* @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: \]\n\} @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: 43\] +^EXIT=0$ +^SIGNAL=0$ +st \(\) -> \{.a=.* @ \[2, 52\]\[Data dependencies: 52, 2\]\[Data dominators: \], .b=.* @ \[5, 52\]\[Data dependencies: 52, 5\]\[Data dominators: \]\} @ \[2, 5, 52\]\[Data dependencies: 52, 5, 2\]\[Data dominators: 52\] +ar \(\) -> \{\[0\] = TOP @ \[11\, 46\]\[Data dependencies: 46\, 11\]\[Data dominators: \]\n\[1\] = TOP @ \[14\, 46\]\[Data dependencies: 46\, 14\]\[Data dominators: \]\n\} @ \[11\, 14\, 46\]\[Data dependencies: 46\, 14\, 11\]\[Data dominators: 46\] +arr \(\) -> \{\[0\] = 1 @ \[19\]\[Data dependencies: 19\]\[Data dominators: 19\]\n\[1\] = 2 @ \[20\]\[Data dependencies: 20\]\[Data dominators: 20\]\n\[2\] = TOP @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: \]\n\} @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: 47\] -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc b/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc index 70491115d3e..9e4cb0a0d34 100644 --- a/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc +++ b/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc @@ -3,29 +3,29 @@ struct-initialization.c --variable --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] .* los.a==0: Success$ -^\[main.assertion.2\] .* los.b==0: Success$ -^\[main.assertion.3\] .* los2.a==3: Success$ -^\[main.assertion.4\] .* los2.b==4: Success$ -^\[main.assertion.5\] .* los3.a==3: Success$ -^\[main.assertion.6\] .* los3.b==4: Success$ -^\[main.assertion.7\] .* los4.a==3: Success$ -^\[main.assertion.8\] .* los4.b==0: Success$ -^\[main.assertion.9\] .* los5.a==0: Success$ -^\[main.assertion.10\] .* los5.b==4: Success$ -^\[main.assertion.11\] .* los6.a==3: Success$ -^\[main.assertion.12\] .* los6.b==4: Success$ -^\[main.assertion.13\] .* lus.a==0: Success$ -^\[main.assertion.14\] .* lus.b==0: Success$ -^\[main.assertion.15\] .* lus2.a==3: Success$ -^\[main.assertion.16\] .* lus2.b==4: Success$ -^\[main.assertion.17\] .* lus3.a==3: Success$ -^\[main.assertion.18\] .* lus3.b==4: Success$ -^\[main.assertion.19\] .* lus4.a==3: Success$ -^\[main.assertion.20\] .* lus4.b==0: Success$ -^\[main.assertion.21\] .* lus5.a==0: Success$ -^\[main.assertion.22\] .* lus5.b==4: Success$ -^\[main.assertion.23\] .* lus6.a==3: Success$ -^\[main.assertion.24\] .* lus6.b==4: Success$ +^\[main\.assertion\.1\] line 27 los.a==0: SUCCESS$ +^\[main\.assertion\.2\] line 28 los.b==0: SUCCESS$ +^\[main\.assertion\.3\] line 29 los2.a==3: SUCCESS$ +^\[main\.assertion\.4\] line 30 los2.b==4: SUCCESS$ +^\[main\.assertion\.5\] line 31 los3.a==3: SUCCESS$ +^\[main\.assertion\.6\] line 32 los3.b==4: SUCCESS$ +^\[main\.assertion\.7\] line 33 los4.a==3: SUCCESS$ +^\[main\.assertion\.8\] line 34 los4.b==0: SUCCESS$ +^\[main\.assertion\.9\] line 35 los5.a==0: SUCCESS$ +^\[main\.assertion\.10\] line 36 los5.b==4: SUCCESS$ +^\[main\.assertion\.11\] line 37 los6.a==3: SUCCESS$ +^\[main\.assertion\.12\] line 38 los6.b==4: SUCCESS$ +^\[main\.assertion\.13\] line 40 lus.a==0: SUCCESS$ +^\[main\.assertion\.14\] line 41 lus.b==0: SUCCESS$ +^\[main\.assertion\.15\] line 42 lus2.a==3: SUCCESS$ +^\[main\.assertion\.16\] line 43 lus2.b==4: SUCCESS$ +^\[main\.assertion\.17\] line 44 lus3.a==3: SUCCESS$ +^\[main\.assertion\.18\] line 45 lus3.b==4: SUCCESS$ +^\[main\.assertion\.19\] line 46 lus4.a==3: SUCCESS$ +^\[main\.assertion\.20\] line 47 lus4.b==0: SUCCESS$ +^\[main\.assertion\.21\] line 48 lus5.a==0: SUCCESS$ +^\[main\.assertion\.22\] line 49 lus5.b==4: SUCCESS$ +^\[main\.assertion\.23\] line 50 lus6.a==3: SUCCESS$ +^\[main\.assertion\.24\] line 51 lus6.b==4: SUCCESS$ -- ^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 9f138fce8ad..400fe99e372 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\] .* 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$ +^\[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/unreachable_assertions_01/test.desc b/regression/goto-analyzer/unreachable_assertions_01/test.desc index 2125fa276e1..7aad7cbf696 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\] .* 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\)$ +^\[main\.assertion\.1\] line 13 0: SUCCESS \(unreachable\)$ +^\[main\.assertion\.2\] line 16 1: SUCCESS \(unreachable\)$ +^\[main\.assertion\.3\] line 19 x == y: SUCCESS \(unreachable\)$ +^\[main\.assertion\.4\] line 22 !\(x == y\) || \(x + 1 + a == b + y\): SUCCESS \(unreachable\)$ +^\[main\.assertion\.5\] line 25 !\(!\(x == y\) || \(x + 1 + a == b + y\)\): SUCCESS \(unreachable\)$ ^EXIT=0$ ^SIGNAL=0$ -- diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc index 9b3c9311d75..fdef4497fa1 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc @@ -3,9 +3,9 @@ main.c --function pass_param --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -\[pass_param\.assertion\.1\] .* b\[0\]==0: Success -\[pass_param\.assertion\.2\] .* b\[1\]==5: Success -\[pass_param\.assertion\.3\] .* b\[1\]==5: Unknown -\[pass_param\.assertion\.4\] .* b\[1\]==6: Unknown -\[pass_param\.assertion\.5\] .* b\[0\]==0: Success --- \ No newline at end of file +\[pass_param\.assertion\.1\] line 13 b\[0\]==0: SUCCESS +\[pass_param\.assertion\.2\] line 16 b\[1\]==5: SUCCESS +\[pass_param\.assertion\.3\] line 22 b\[1\]==5: UNKNOWN +\[pass_param\.assertion\.4\] line 23 b\[1\]==6: UNKNOWN +\[pass_param\.assertion\.5\] line 26 b\[0\]==0: SUCCESS +-- diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc index a6fe7cfe1e8..57435da1a68 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc @@ -3,7 +3,7 @@ main.c --function test_param_function --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -[test_param_function.assertion.1] .* a==5: Success -[test_param_function.assertion.2] .* a==10: Unknown -[test_param_function.assertion.3] .* b==7: Success --- \ No newline at end of file +\[test_param_function.assertion\.1\] line 15 a==5: SUCCESS +\[test_param_function.assertion\.2\] line 24 a==10: UNKNOWN +\[test_param_function.assertion\.3\] line 25 b==7: SUCCESS +-- diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/test.desc index e62079ecc21..2f659f02b22 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/test.desc @@ -3,9 +3,9 @@ main.c --function test_non_terminating --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -[test_non_terminating.assertion.1] .* one_val==5: Success -[test_non_terminating.assertion.2] .* second_val==6: Success -[test_non_terminating.assertion.3] .* one_val==10: Success \(unreachable\) -[test_non_terminating.assertion.4] .* second_val==12: Success \(unreachable\) -[test_non_terminating.assertion.5] .* second_val==13: Success \(unreachable\) --- \ No newline at end of file +\[test_non_terminating.assertion\.1\] line 23 one_val==5: SUCCESS +\[test_non_terminating.assertion\.2\] line 24 second_val==6: SUCCESS +\[test_non_terminating.assertion\.3\] line 27 one_val==10: SUCCESS \(unreachable\) +\[test_non_terminating.assertion\.4\] line 29 second_val==12: SUCCESS \(unreachable\) +\[test_non_terminating.assertion\.5\] line 31 second_val==13: SUCCESS \(unreachable\) +-- diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc index 1182dddcb3b..3e43bb8f38a 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc @@ -3,12 +3,12 @@ main.c --function pointer_test --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[pointer_test.assertion.1\] file main.c line 41 function pointer_test, j==1: Success$ -^\[pointer_test.assertion.2\] file main.c line 42 function pointer_test, i==10: Success$ -^\[pointer_test.assertion.3\] file main.c line 47 function pointer_test, j==2: Success$ -^\[pointer_test.assertion.4\] file main.c line 48 function pointer_test, i==10: Success$ -^\[pointer_test.assertion.5\] file main.c line 53 function pointer_test, j==3: Success$ -^\[pointer_test.assertion.6\] file main.c line 54 function pointer_test, i==11: Unknown$ -^\[pointer_test.assertion.7\] file main.c line 59 function pointer_test, j==4: Success$ -^\[pointer_test.assertion.8\] file main.c line 60 function pointer_test, i==11: Unknown$ --- \ No newline at end of file +^\[pointer_test.assertion\.1\] line 41 j==1: SUCCESS$ +^\[pointer_test.assertion\.2\] line 42 i==10: SUCCESS$ +^\[pointer_test.assertion\.3\] line 47 j==2: SUCCESS$ +^\[pointer_test.assertion\.4\] line 48 i==10: SUCCESS$ +^\[pointer_test.assertion\.5\] line 53 j==3: SUCCESS$ +^\[pointer_test.assertion\.6\] line 54 i==11: UNKNOWN$ +^\[pointer_test.assertion\.7\] line 59 j==4: SUCCESS$ +^\[pointer_test.assertion\.8\] line 60 i==11: UNKNOWN$ +-- diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc index 50a8e8c90e2..ff7983d6d35 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc @@ -3,9 +3,9 @@ main.c --function simple_test --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[simple_test.assertion.1\] file main.c line 25 function simple_test, i==0: Success$ -^\[simple_test.assertion.2\] file main.c line 26 function simple_test, global==0: Success$ -^\[simple_test.assertion.3\] file main.c line 31 function simple_test, i==1: Success$ -^\[simple_test.assertion.4\] file main.c line 32 function simple_test, global==2: Success$ +^\[simple_test\.assertion\.1\] line 25 i==0: SUCCESS$ +^\[simple_test\.assertion\.2\] line 26 global==0: SUCCESS$ +^\[simple_test\.assertion\.3\] line 31 i==1: SUCCESS$ +^\[simple_test\.assertion\.4\] line 32 global==2: SUCCESS$ --- \ No newline at end of file +-- diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc index 2f9590aff78..fdbc292e024 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc @@ -3,6 +3,6 @@ main.c --function global_test --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[global_test.assertion.1\] file main.c line 67 function global_test, global==42: Success$ -^\[global_test.assertion.2\] file main.c line 70 function global_test, global==50: Unknown$ --- \ No newline at end of file +^\[global_test\.assertion\.1\] line 67 global==42: SUCCESS$ +^\[global_test\.assertion\.2\] line 70 global==50: UNKNOWN$ +-- diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc index ab3a2603306..a0107fef2fb 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc @@ -3,12 +3,12 @@ main.c --function pass_param --variable --pointers --arrays --structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[pass_param.assertion.1\] .* human_instance.age==24: Success$ -^\[pass_param.assertion.2\] .* human_instance.height==1.80: Success$ -^\[pass_param.assertion.3\] .* human_instance.age==10: Success$ -^\[pass_param.assertion.4\] .* human_instance.age==24: Failure \(if reachable\)$ -^\[pass_param.assertion.5\] .* human_instance.height==1.80: Success$ -^\[pass_param.assertion.6\] .* human_instance.age==32: Unknown$ -^\[pass_param.assertion.7\] .* human_instance.age==10: Unknown$ -^\[pass_param.assertion.8\] .* human_instance.height==1.80: Success$ --- \ No newline at end of file +^\[pass_param\.assertion\.1\] line 25 human_instance.age==24: SUCCESS$ +^\[pass_param\.assertion\.2\] line 26 human_instance.height==1.80: SUCCESS$ +^\[pass_param\.assertion\.3\] line 29 human_instance.age==10: SUCCESS$ +^\[pass_param\.assertion\.4\] line 30 human_instance.age==24: FAILURE \(if reachable\)$ +^\[pass_param\.assertion\.5\] line 31 human_instance.height==1.80: SUCCESS$ +^\[pass_param\.assertion\.6\] line 34 human_instance.age==32: UNKNOWN$ +^\[pass_param\.assertion\.7\] line 35 human_instance.age==10: UNKNOWN$ +^\[pass_param\.assertion\.8\] line 36 human_instance.height==1.80: SUCCESS$ +-- diff --git a/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc b/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc index f7c393c437b..110a280ee8b 100644 --- a/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc @@ -3,6 +3,6 @@ main.c --function main --variable --structs --verify ^EXIT=0$ ^SIGNAL=0$ -\[main\.assertion\.1\] .* bs\.byte==10: Success -\[main\.assertion\.2\] .* bs\.bitfield==1: Success +\[main\.assertion\.1\] line 12 bs\.byte==10: SUCCESS +\[main\.assertion\.2\] line 13 bs\.bitfield==1: SUCCESS -- diff --git a/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc b/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc index 402ca88b869..f7974e65b0a 100644 --- a/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc @@ -3,6 +3,6 @@ main.c --function main --variable --structs --interval-values --verify ^EXIT=0$ ^SIGNAL=0$ -\[main\.assertion\.1\] .* bs\.byte==10: Success -\[main\.assertion\.2\] .* bs\.bitfield==1: Success +\[main\.assertion\.1\] line 12 bs\.byte==10: SUCCESS +\[main\.assertion\.2\] line 13 bs\.bitfield==1: SUCCESS -- diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc index dad9a91adca..7b8fdc8233e 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc @@ -1,7 +1,7 @@ CORE main.c --dependence-graph-vs --structs --arrays --verify -EXIT=0 -SIGNAL=0 -^\[main.assertion.1\] file .* function main, s_str.idx > 1: Unknown$ +^EXIT=0$ +^SIGNAL=0$ +^\[main\.assertion\.1\] line 20 s_str.idx > 1: UNKNOWN$ -- diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc index c9f81268709..d3fbd5ad478 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc @@ -1,37 +1,37 @@ CORE main.c file1.c file2.c --dependence-graph-vs --structs --arrays --show -EXIT=0 -SIGNAL=0 -Data dependencies: 53 \[st.a\] -Data dependencies: 53 \[st.b\] -Data dependencies: 1 \[st.a\], 53 \[st.a\] -Data dependencies: 4 \[st.b\], 53 \[st.b\] -Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\] -Data dependencies: 48 \[ar\[\(signed long int\)0\]\] -Data dependencies: 48 \[ar\[\(signed long int\)1\]\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\] -Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\] +^EXIT=0$ +^SIGNAL=0$ +Data dependencies: 58 \[st.a\] +Data dependencies: 58 \[st.b\] +Data dependencies: 1 \[st.a\], 58 \[st.a\] +Data dependencies: 4 \[st.b\], 58 \[st.b\] +Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\] +Data dependencies: 52 \[ar\[\(signed long int\)0\]\] +Data dependencies: 52 \[ar\[\(signed long int\)1\]\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\] +Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\] Data dependencies: 19 \[arr\[\(signed long int\)1\]\] Data dependencies: 18 \[arr\[\(signed long int\)0\]\] Data dependencies: 19 \[arr\[\(signed long int\)1\]\] Data dependencies: 20 \[arr\[\(signed long int\)2\]\], 22 \[arr\[\(signed long int\)2\]\] -Data dependencies: 1 \[st.a\], 53 \[st.a\], 57 \[st.a\] -Data dependencies: 4 \[st.b\], 53 \[st.b\], 60 \[st.b\] -Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\], 57 \[st.a\], 60 \[st.b\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\], 68 \[ar\[\(signed long int\)0\]\] -Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\], 71 \[ar\[\(signed long int\)1\]\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 68 \[ar\[\(signed long int\)0\]\], 71 \[ar\[\(signed long int\)1\]\] -Data dependencies: 1 \[st.a\], 53 \[st.a\] -Data dependencies: 4 \[st.b\], 53 \[st.b\] -Data dependencies: 1 \[st.a\], 53 \[st.a\], 57 \[st.a\] -Data dependencies: 4 \[st.b\], 53 \[st.b\], 60 \[st.b\] -Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\], 57 \[st.a\], 60 \[st.b\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\] -Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\], 68 \[ar\[\(signed long int\)0\]\] -Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\], 71 \[ar\[\(signed long int\)1\]\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 68 \[ar\[\(signed long int\)0\]\], 71 \[ar\[\(signed long int\)1\]\] +Data dependencies: 1 \[st.a\], 58 \[st.a\], 62 \[st.a\] +Data dependencies: 4 \[st.b\], 58 \[st.b\], 65 \[st.b\] +Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\], 62 \[st.a\], 65 \[st.b\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\], 73 \[ar\[\(signed long int\)0\]\] +Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\], 76 \[ar\[\(signed long int\)1\]\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 73 \[ar\[\(signed long int\)0\]\], 76 \[ar\[\(signed long int\)1\]\] +Data dependencies: 1 \[st.a\], 58 \[st.a\] +Data dependencies: 4 \[st.b\], 58 \[st.b\] +Data dependencies: 1 \[st.a\], 58 \[st.a\], 62 \[st.a\] +Data dependencies: 4 \[st.b\], 58 \[st.b\], 65 \[st.b\] +Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\], 62 \[st.a\], 65 \[st.b\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\] +Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\], 73 \[ar\[\(signed long int\)0\]\] +Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\], 76 \[ar\[\(signed long int\)1\]\] +Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 73 \[ar\[\(signed long int\)0\]\], 76 \[ar\[\(signed long int\)1\]\] -- ^warning: ignoring diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc index 017a185317f..ce8b4f92a48 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc @@ -1,38 +1,38 @@ CORE main.c file1.c file2.c --dependence-graph-vs --structs --arrays --show -EXIT=0 -SIGNAL=0 -^Data dependencies: 53 \[st.a\]$ -^Data dependencies: 53 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 53 \[st.a\]$ -^Data dependencies: 4 \[st.b\], 53 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\]$ -^Data dependencies: 48 \[ar\[\(signed long int\)0\]\]$ +^EXIT=0$ +^SIGNAL=0$ +^Data dependencies: 58 \[st.a\]$ +^Data dependencies: 58 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 58 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 58 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\]$ +^Data dependencies: 52 \[ar\[\(signed long int\)0\]\]$ ^Data dependencies: 6 \[out1\]$ -^Data dependencies: 48 \[ar\[\(signed long int\)1\]\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\]$ -^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\]$ +^Data dependencies: 52 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\]$ +^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\]$ ^Data dependencies: 19 \[arr\[\(signed long int\)1\]\]$ ^Data dependencies: 18 \[arr\[\(signed long int\)0\]\]$ ^Data dependencies: 19 \[arr\[\(signed long int\)1\]\]$ ^Data dependencies: 20 \[arr\[\(signed long int\)2\]\], 22 \[arr\[\(signed long int\)2\]\]$ -^Data dependencies: 1 \[st.a\], 53 \[st.a\], 57 \[st.a\]$ -^Data dependencies: 4 \[st.b\], 53 \[st.b\], 60 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\], 57 \[st.a\], 60 \[st.b\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\], 68 \[ar\[\(signed long int\)0\]\]$ -^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\], 71 \[ar\[\(signed long int\)1\]\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 68 \[ar\[\(signed long int\)0\]\], 71 \[ar\[\(signed long int\)1\]\]$ -^Data dependencies: 1 \[st.a\], 53 \[st.a\]$ -^Data dependencies: 4 \[st.b\], 53 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 53 \[st.a\], 57 \[st.a\]$ -^Data dependencies: 4 \[st.b\], 53 \[st.b\], 60 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 4 \[st.b\], 53 \[st.a, st.b\], 57 \[st.a\], 60 \[st.b\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\]$ -^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 48 \[ar\[\(signed long int\)0\]\], 68 \[ar\[\(signed long int\)0\]\]$ -^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)1\]\], 71 \[ar\[\(signed long int\)1\]\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 48 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 68 \[ar\[\(signed long int\)0\]\], 71 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 1 \[st.a\], 58 \[st.a\], 62 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 58 \[st.b\], 65 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\], 62 \[st.a\], 65 \[st.b\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\], 73 \[ar\[\(signed long int\)0\]\]$ +^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\], 76 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 73 \[ar\[\(signed long int\)0\]\], 76 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 1 \[st.a\], 58 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 58 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 58 \[st.a\], 62 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 58 \[st.b\], 65 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\], 62 \[st.a\], 65 \[st.b\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\]$ +^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\], 73 \[ar\[\(signed long int\)0\]\]$ +^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\], 76 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 73 \[ar\[\(signed long int\)0\]\], 76 \[ar\[\(signed long int\)1\]\]$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph15/main.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph15/main.c new file mode 100644 index 00000000000..f8e7aae8585 --- /dev/null +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph15/main.c @@ -0,0 +1,23 @@ +int f2(int, const int*); +extern const int g_map[]; + +int g_out1; +int g_out2; + +extern int g_in; + +void main(void) +{ + int t1; + int t2; + + t1 = g_in; + t2 = f2(t1, g_map); + + if (t2 >= 0) + g_out1 = t2; + else + g_out1 = 0; + + g_out2 = t1; +} diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph15/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph15/test.desc index d9a7d78a58f..6217396b36b 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph15/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph15/test.desc @@ -1,5 +1,5 @@ CORE -../dependence-graph15/main.c +main.c --show --dependence-graph-vs activate-multi-line-match ^EXIT=0$ diff --git a/regression/goto-analyzer/dependence-graph16/main.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph16/main.c similarity index 100% rename from regression/goto-analyzer/dependence-graph16/main.c rename to regression/goto-analyzer/variable-sensitivity-dependence-graph16/main.c diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph16/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph16/test.desc index ea7b68ebd01..0d729bc4a85 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph16/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph16/test.desc @@ -1,9 +1,9 @@ CORE -../dependence-graph16/main.c +main.c --dependence-graph-vs --show activate-multi-line-match -EXIT=0 -SIGNAL=0 +^EXIT=0$ +^SIGNAL=0$ // Assignment from the result of a function call to a function with no body // should have a data dependency on the function ^Data dependencies: 3 \[f2\]\n(.*\n).*\/\/ 4 file .*main.c line 15 function main\n.*t2 = NONDET\(signed int\); diff --git a/regression/goto-analyzer/dependence-graph17/main.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/main.c similarity index 100% rename from regression/goto-analyzer/dependence-graph17/main.c rename to regression/goto-analyzer/variable-sensitivity-dependence-graph17/main.c diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc index 8e8469d4d32..3df8ae018d1 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc @@ -1,8 +1,8 @@ CORE -../dependence-graph17/main.c +main.c --dependence-graph-vs --arrays --show activate-multi-line-match -EXIT=0 -SIGNAL=0 -\*\*\*\* 9 file main\.c line 22 function main\nControl dependencies: 28 \[UNCONDITIONAL\]\nData dependencies: 1 \[g_a\[\(signed long int\)i\]\], 2 \[g_a\[\(signed long int\)i\]\], 3 \[g_a\[\(signed long int\)i\]\], 4 \[i\], 6 \[i\], 7 \[g_a\[\(signed long int\)i\]\] +^EXIT=0$ +^SIGNAL=0$ +\*\*\*\* 9 file .*main\.c line 22 function main\nControl dependencies: 34 \[UNCONDITIONAL\]\nData dependencies: 1 \[g_a\[\(signed long int\)i\]\], 2 \[g_a\[\(signed long int\)i\]\], 3 \[g_a\[\(signed long int\)i\]\], 7 \[g_a\[\(signed long int\)i\]\] -- diff --git a/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/test.desc b/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/test.desc index 13d621c5d9e..9686aecf8bb 100644 --- a/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/test.desc @@ -3,7 +3,7 @@ main.c --variable --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] file main.c line \d\d function main, assertion small_0_1 < big_0_1: Success -^\[main.assertion.2\] file main.c line \d\d function main, assertion one / 10.0f < 0.2f: Success -^\[main.assertion.3\] file main.c line \d\d function main, assertion one_tenth_ish < 0.2f: Unknown -^\[main.assertion.4\] file main.c line \d\d function main, assertion 10.0f / five == 2.0f: Success +^\[main.assertion\.1\] line 12 assertion small_0_1 < big_0_1: SUCCESS +^\[main.assertion\.2\] line 24 assertion one / 10.0f < 0.2f: SUCCESS +^\[main.assertion\.3\] line 33 assertion one_tenth_ish < 0.2f: UNKNOWN +^\[main.assertion\.4\] line 38 assertion 10.0f / five == 2.0f: SUCCESS diff --git a/regression/goto-analyzer/variable-sensitivity-function-call/test.desc b/regression/goto-analyzer/variable-sensitivity-function-call/test.desc index e847cd4bfa8..57b44330204 100644 --- a/regression/goto-analyzer/variable-sensitivity-function-call/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-function-call/test.desc @@ -3,5 +3,5 @@ main.c --variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ -\[main.assertion.1\] file main.c line 19 function main, t1 == 5 after calling function with missing body: Success +\[main\.assertion\.1\] line 19 t1 == 5 after calling function with missing body: SUCCESS -- diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/test.desc index 4bbbcd58c41..ccf04bdc5e3 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/test.desc @@ -3,5 +3,5 @@ main.c --variable-sensitivity --interval-values --show ^EXIT=0$ ^SIGNAL=0$ -main::1::z \(\) -> \[00000000000000000000000000000011, 00000000000000000000000000000011\] +main::1::z \(\) -> \[3, 3\] @ \[5\] -- diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/test.desc index e6da64be919..efc8c529e7b 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/test.desc @@ -3,5 +3,5 @@ main.c --variable-sensitivity --interval-values --show ^EXIT=0$ ^SIGNAL=0$ -main::1::z \(\) -> \[00000000000000000000000000000011, 00000000000000000000000000000100\] +main::1::z \(\) -> \[3, 4\] @ \[9\] -- diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/test.desc index 0d93a20e4a3..b231fd0f0b4 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/test.desc @@ -3,5 +3,5 @@ main.c --variable-sensitivity --interval-values --show ^EXIT=0$ ^SIGNAL=0$ -main::1::a \(\) -> \[00000000000000000000000000000110, 00000000000000000000000000000110\] +main::1::a \(\) -> \[6, 6\] @ \[7\] -- diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/test.desc index e15cedd3f15..7b9ae83393d 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/test.desc @@ -1,5 +1,7 @@ CORE main.c --show --variable-sensitivity --interval-values --arrays -main::1::second_value \(\) -> \[00000000000000000000000000000010, 00000000000000000000000000000010\] -main::1::second_value_after_write \(\) -> \[00000000000000000000000000001010, 00000000000000000000000000001010\] \ No newline at end of file +^EXIT=0$ +^SIGNAL=0$ +main::1::second_value \(\) -> \[2, 2\] @ \[3\] +main::1::second_value_after_write \(\) -> \[A, A\] @ \[6\] diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/test.desc index c342ebc519e..738ea085c60 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/test.desc @@ -1,7 +1,9 @@ CORE main.c --show --variable-sensitivity --interval-values --arrays -main::1::arr_at_ix \(\) -> \[00000000000000000000000000000001, 00000000000000000000000000000011\] -main::1::arr_0_after_write \(\) -> \[00000000000000000000000000000001, 00000000000000000000000000000100\] -main::1::arr_1_after_write \(\) -> \[00000000000000000000000000000010, 00000000000000000000000000000100\] -main::1::arr_2_after_write \(\) -> \[00000000000000000000000000000011, 00000000000000000000000000000011\] \ No newline at end of file +^EXIT=0$ +^SIGNAL=0$ +main::1::arr_at_ix \(\) -> \[1, 3\] @ \[9\] +main::1::arr_0_after_write \(\) -> \[1, 4\] @ \[18\] +main::1::arr_1_after_write \(\) -> \[2, 4\] @ \[20\] +main::1::arr_2_after_write \(\) -> \[3, 3\] @ \[22\] diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc index c619d4f2182..32d066eee9c 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc @@ -3,9 +3,9 @@ main.c --variable-sensitivity --interval-values --structs --pointers --show ^EXIT=0$ ^SIGNAL=0$ -main::1::vecMinusTenAndTen \(\) -> \{.x=\[11111111111111111111111111110110, 11111111111111111111111111110110\] \@ \[\d*\], .y=\[00000000000000000000000000001010, 00000000000000000000000000001010\] \@ \[\d*\]\} -main::1::1::vecZero \(\) -> \{.x=\[00000000000000000000000000000000, 00000000000000000000000000000000\] \@ \[\d*\], .y=\[00000000000000000000000000000000, 00000000000000000000000000000000\] \@ \[\d*\]\} \@ \[\d*] -main::1::2::vecOne \(\) -> \{.x=\[00000000000000000000000000000001, 00000000000000000000000000000001\] \@ \[\d*\], .y=\[00000000000000000000000000000001, 00000000000000000000000000000001\] \@ \[\d*\]\} \@ \[\d*\] -main::1::vecZeroOrOne \(\) -> \{.x=\[00000000000000000000000000000000, 00000000000000000000000000000001\] \@ \[\d*\], .y=\[00000000000000000000000000000000, 00000000000000000000000000000001\] \@ \[\d*\]\} \@ \[\d*\] -main::1::vecThirteenAndFourtyTwo \(\) -> \{.x=\[00000000000000000000000000001101, 00000000000000000000000000001101\] \@ \[\d*\], .y=\[00000000000000000000000000101010, 00000000000000000000000000101010\] \@ \[\d*\]\} \@ \[\d*\] +main::1::vecMinusTenAndTen \(\) -> \{.x=\[FFFFFFF6, FFFFFFF6\] \@ \[3\], .y=\[A, A\] \@ \[3\]\} @ \[3\] +main::1::1::vecZero \(\) -> \{.x=\[0, 0\] \@ \[8\], .y=\[0, 0\] \@ \[8\]\} \@ \[8\] +main::1::2::vecOne \(\) -> \{.x=\[1, 1\] \@ \[13\], .y=\[1, 1\] \@ \[13\]\} \@ \[13\] +main::1::vecZeroOrOne \(\) -> \{.x=\[0, 1\] \@ \[17\], .y=\[0, 1\] \@ \[17\]\} \@ \[17\] +main::1::vecThirteenAndFourtyTwo \(\) -> \{.x=\[D, D\] \@ \[21\], .y=\[2A, 2A\] \@ \[21\]\} \@ \[21\] -- diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc index 4f16401e531..ba22ca83685 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc @@ -3,6 +3,6 @@ main.c --variable-sensitivity --interval-values --show ^EXIT=0$ ^SIGNAL=0$ -main::1::b1 \(\) -> \[00000001, 00000001\] -main::1::b2 \(\) -> \[00000000, 00000000\] +main::1::b1 \(\) -> \[1, 1\] @ \[2\] +main::1::b2 \(\) -> \[0, 0\] -- diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/test.desc index 6c1444dd97e..1e09d532f7c 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/test.desc @@ -1,8 +1,8 @@ CORE main.c --variable-sensitivity --interval-values --verify -\[main.assertion.*\] .* function main, x > y, z == 1: Success -\[main.assertion.*\] .* function main, x < y, z == 1: Success +\[main\.assertion\.1\] line 10 x > y, z == 1: SUCCESS +\[main\.assertion\.2\] line 17 x < y, z == 1: SUCCESS ^EXIT=0$ ^SIGNAL=0$ -- diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/test.desc index 8a113f6e525..12e1dd0af21 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/test.desc @@ -3,5 +3,5 @@ main.c --variable-sensitivity --interval-values --show ^EXIT=0$ ^SIGNAL=0$ -main::1::r \(\) -> TOP -main::1::s \(\) -> \[00000000000000000000000000000000, 00000000000000000000000000000000\] +main::1::r \(\) -> TOP @ \[1\] +main::1::s \(\) -> \[0, 0\] @ \[3\] diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values/test.desc index dd538280683..fd0a39db9f0 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values/test.desc @@ -3,9 +3,9 @@ main.c --variable-sensitivity --interval-values --show ^EXIT=0$ ^SIGNAL=0$ -main::1::zero \(\) -> \[00000000000000000000000000000000, 00000000000000000000000000000000\] -main::1::1::one \(\) -> \[00000000000000000000000000000001, 00000000000000000000000000000001\] -main::1::2::minus_one \(\) -> \[11111111111111111111111111111111, 11111111111111111111111111111111\] -main::1::between_minus_one_and_one \(\) -> \[11111111111111111111111111111111, 00000000000000000000000000000001\] -main::1::thirteen \(\) -> \[00000000000000000000000000001101, 00000000000000000000000000001101\] --- \ No newline at end of file +main::1::zero \(\) -> \[0, 0\] @ \[3\] +main::1::1::one \(\) -> \[1, 1\] @ \[8\] +main::1::2::minus_one \(\) -> \[FFFFFFFF, FFFFFFFF\] @ \[13\] +main::1::between_minus_one_and_one \(\) -> \[FFFFFFFF, 1\] @ \[17\] +main::1::thirteen \(\) -> \[D, D\] @ \[20\] +-- diff --git a/regression/goto-analyzer/write-stack-types/test.desc b/regression/goto-analyzer/write-stack-types/test.desc index 6645d1f5645..d148b1ae7ef 100644 --- a/regression/goto-analyzer/write-stack-types/test.desc +++ b/regression/goto-analyzer/write-stack-types/test.desc @@ -3,6 +3,6 @@ write-stack-address-of.c --variable --structs --pointers --verify ^EXIT=0$ ^SIGNAL=0$ -^\[func1.assertion.1\] .* func1.a == 0: Unknown$ +^\[func1\.assertion\.1\] line 15 func1.a == 0: UNKNOWN$ -- ^warning: ignoring diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 219c88b2b23..32dbefc5de0 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -204,7 +204,7 @@ bool abstract_environmentt::assign( } else { - lhs_value=map.const_find(symbol_expr).first; + lhs_value = map.find(symbol_expr.get_identifier()).value(); } } @@ -247,7 +247,7 @@ bool abstract_environmentt::assign( if(final_value != lhs_value) { - map[symbol_expr]=final_value; + map.insert_or_replace(symbol_expr.get_identifier(), final_value); } } return true; @@ -492,16 +492,18 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) // 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.get_delta_view(map)) + decltype(env.map)::delta_viewt delta_view; + env.map.get_delta_view(map, delta_view); + for(const auto &entry : delta_view) { bool object_modified=false; - abstract_object_pointert new_object= + abstract_object_pointert new_object = abstract_objectt::merge( - entry.other_m, + entry.get_other_map_value(), entry.m, object_modified); modified|=object_modified; - map.find(entry.k, tvt(true)).first=new_object; + map.replace(entry.k, new_object); } return modified; @@ -620,10 +622,11 @@ void abstract_environmentt::output( { out << "{\n"; - for(const auto &entry : map.get_view()) + decltype(map)::viewt view; + map.get_view(view); + for(const auto &entry : view) { - out << entry.first.get_identifier() - << " () -> "; + out << entry.first << " () -> "; entry.second->output(out, ai, ns); out << "\n"; } @@ -644,7 +647,9 @@ Function: abstract_environmentt::verify bool abstract_environmentt::verify() const { - for(const auto &entry : map.get_view()) + decltype(map)::viewt view; + map.get_view(view); + for(const auto &entry : view) { if(entry.second == nullptr) { @@ -690,7 +695,7 @@ Function: abstract_environmentt::erase void abstract_environmentt::erase(const symbol_exprt &expr) { - map.erase(expr); + map.erase_if_exists(expr.get_identifier()); } /*******************************************************************\ @@ -713,17 +718,20 @@ Function: abstract_environmentt::environment_diff \*******************************************************************/ -std::vector abstract_environmentt::modified_symbols( +std::vector +abstract_environmentt::modified_symbols( const abstract_environmentt &first, const abstract_environmentt &second) { // Find all symbols who have different write locations in each map - std::vector symbols_diff; - for (const auto &entry : first.map.get_view()) + std::vector symbols_diff; + decltype(first.map)::viewt view; + first.map.get_view(view); + for(const auto &entry : view) { - const auto second_entry = second.map.const_find(entry.first); - if (second_entry.second) + const auto second_entry = second.map.find(entry.first); + if (second_entry.has_value()) { - if(second_entry.first->has_been_modified(entry.second)) + if(second_entry.value().get()->has_been_modified(entry.second)) symbols_diff.push_back(entry.first); } } @@ -732,7 +740,7 @@ std::vector abstract_environmentt::modified_symbols( for(const auto &entry : second.map.get_view()) { const auto &second_entry = first.map.find(entry.first); - if (!second_entry.second) + if (!second_entry.has_value()) { symbols_diff.push_back(entry.first); } @@ -744,7 +752,7 @@ static std::size_t count_globals(const namespacet &ns) { auto const& symtab = ns.get_symbol_table(); auto val = std::count_if(symtab.begin(), symtab.end(), - [](const symbol_table_baset::const_iteratort::value_type& sym) { + [](const symbol_tablet::const_iteratort::value_type& sym) { return sym.second.is_lvalue && sym.second.is_static_lifetime; }); return val; diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 7a3868fbe82..48083e8b1e5 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -23,6 +23,7 @@ class abstract_environmentt { public: + using map_keyt = irep_idt; abstract_environmentt(); // These three are really the heart of the method virtual abstract_object_pointert eval( @@ -70,7 +71,7 @@ class abstract_environmentt bool verify() const; - static std::vector modified_symbols( + static std::vector modified_symbols( const abstract_environmentt &first, const abstract_environmentt &second); @@ -83,7 +84,6 @@ class abstract_environmentt virtual abstract_object_pointert eval_expression( const exprt &e, const namespacet &ns) const; - typedef symbol_exprt map_keyt; sharing_mapt map; private: diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index b77326a41e9..b40374191f1 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -542,7 +542,7 @@ void abstract_objectt::dump_map_diff( bool first = true; for(auto &item : delta_view) { - out << (first ? "" : ", ") << item.k << "=" << item.in_both; + out << (first ? "" : ", ") << item.k << "=" << item.is_in_both_maps(); first = false; } out << "}"; diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index ac55b5e5601..0ad74b8a19b 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -131,7 +131,7 @@ class abstract_objectt:public std::enable_shared_from_this std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; typedef std::set locationst; - typedef sharing_mapt + typedef sharing_mapt shared_mapt; static void dump_map(std::ostream out, const shared_mapt &m); @@ -277,9 +277,9 @@ class abstract_objectt:public std::enable_shared_from_this template static bool merge_shared_maps( - const sharing_mapt &map1, - const sharing_mapt &map2, - sharing_mapt &out_map); + const sharing_mapt &map1, + const sharing_mapt &map2, + sharing_mapt &out_map); @@ -335,23 +335,25 @@ bool abstract_objectt::merge_maps( template bool abstract_objectt::merge_shared_maps( - const sharing_mapt &m1, - const sharing_mapt &m2, - sharing_mapt &out_map) + const sharing_mapt &m1, + const sharing_mapt &m2, + sharing_mapt &out_map) { bool modified=false; - auto delta_view = m1.get_delta_view(m2, true); + typename sharing_mapt:: + delta_viewt delta_view; + m1.get_delta_view(m2, delta_view, true); for(auto &item : delta_view) { bool changes = false; abstract_object_pointert v_new = abstract_objectt::merge( - item.m, item.other_m, changes); + item.m, item.get_other_map_value(), changes); if (changes) { modified = true; - out_map[item.k] = v_new; + out_map.replace(item.k, v_new); } } diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index c09ed72b7bc..9d4c2b2876d 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -82,10 +82,7 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( int index=0; for(const exprt &entry : expr.operands()) { - map.insert( - mp_integer(index), - environment.eval(entry, ns), - tvt(false)); + map.insert(mp_integer(index), environment.eval(entry, ns)); ++index; } clear_top(); @@ -275,16 +272,16 @@ abstract_object_pointert constant_array_abstract_objectt::read_index( mp_integer index_value; if(eval_index(index, env, ns, index_value)) { - shared_array_mapt::const_find_type value = map.find(index_value); + auto const value = map.find(index_value); // Here we are assuming it is always in bounds - if(!value.second) + if(!value.has_value()) { return env.abstract_object_factory(type().subtype(), ns, true, false); } else { - return value.first; + return value.value(); } } else @@ -358,20 +355,21 @@ sharing_ptrt { // We were able to evaluate the index to a value, which we // assume is in bounds... - shared_array_mapt::const_find_type old_value = map.find(index_value); + auto const old_value = map.find(index_value); - if(!old_value.second) + if(!old_value.has_value()) { result->map.insert( index_value, environment.write( - get_top_entry(environment, ns), value, stack, ns, merging_write), - tvt(false)); + get_top_entry(environment, ns), value, stack, ns, merging_write)); } else { - result->map.find(index_value, tvt(true)).first = - environment.write(old_value.first, value, stack, ns, merging_write); + result->map.replace( + index_value, + environment.write( + old_value.value(), value, stack, ns, merging_write)); } result->clear_top(); @@ -387,8 +385,9 @@ sharing_ptrt for(const auto &starting_value : view) { // Merging write since we don't know which index we are writing to - result->map.find(starting_value.first, tvt(true)).first = - environment.write(starting_value.second, value, stack, ns, true); + result->map.replace( + starting_value.first, + environment.write(starting_value.second, value, stack, ns, true)); result->clear_top(); } @@ -414,10 +413,9 @@ sharing_ptrt INVARIANT(!result->map.empty(), "If not top, map cannot be empty"); - shared_array_mapt::const_find_type old_value= - result->map.find(index_value); + auto const old_value = result->map.find(index_value); - if(!old_value.second) // Array element is top + if(!old_value.has_value()) // Array element is top { DATA_INVARIANT(result->verify(), "Structural invariants maintained"); return result; @@ -425,26 +423,26 @@ sharing_ptrt bool dummy; - result->map.find(index_value, tvt(true)).first = - abstract_objectt::merge(old_value.first, value, dummy); + result->map.replace( + index_value, + abstract_objectt::merge(old_value.value(), value, dummy)); DATA_INVARIANT(result->verify(), "Structural invariants maintained"); return result; } else { - shared_array_mapt::find_type old_value= - result->map.find(index_value); - if(old_value.second) + auto const old_value = result->map.find(index_value); + if(old_value.has_value()) { - if(value != old_value.first) + if(value != abstract_object_pointert{old_value.value()}) { - old_value.first = value; + result->map.replace(index_value, value); } } else { - result->map.insert(index_value, value, tvt(false)); + result->map.insert(index_value, value); } result->clear_top(); DATA_INVARIANT(result->verify(), "Structural invariants maintained"); @@ -544,7 +542,7 @@ constant_array_abstract_objectt::visit_sub_elements( auto newval = visitor.visit(item.second); if(newval != item.second) { - result->map.find(item.first, tvt(true)).first = newval; + result->map.replace(item.first, std::move(newval)); modified = true; } } diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index c6bf182ba10..293686b3cdb 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -81,7 +81,7 @@ class constant_array_abstract_objectt:public array_abstract_objectt size_t operator()(const mp_integer &i) const { return std::hash{}(i.to_ulong()); } }; - typedef sharing_mapt + typedef sharing_mapt shared_array_mapt; shared_array_mapt map; diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 688b6727805..f161ff50d3f 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -95,7 +95,7 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( struct_abstract_objectt(e, environment, ns) { PRECONDITION(ns.follow(e.type()).id()==ID_struct); - + const struct_typet struct_type_def = to_struct_type(ns.follow(e.type())); bool did_initialize_values = false; @@ -104,8 +104,9 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( param_it != e.operands().end(); ++param_it) { - map[struct_type_it->get_name()]=environment.abstract_object_factory - (param_it->type(), *param_it, ns); + map.insert_or_replace( + struct_type_it->get_name(), + environment.abstract_object_factory (param_it->type(), *param_it, ns)); did_initialize_values = true; ++struct_type_it; } @@ -157,11 +158,11 @@ abstract_object_pointert full_struct_abstract_objectt::read_component( const irep_idt c=member_expr.get_component_name(); - shared_struct_mapt::const_find_type value=map.find(c); + auto const value = map.find(c); - if(value.second) + if(value.has_value()) { - return value.first; + return value.value(); } else { @@ -220,21 +221,21 @@ sharing_ptrt { abstract_object_pointert starting_value; const irep_idt c=member_expr.get_component_name(); - shared_struct_mapt::const_find_type old_value = map.find(c); - if(!old_value.second) + auto const old_value = map.find(c); + if(!old_value.has_value()) { starting_value= environment.abstract_object_factory( member_expr.type(), ns, true, false); result->map.insert( c, - environment.write(starting_value, value, stack, ns, merging_write), - tvt(false)); + environment.write(starting_value, value, stack, ns, merging_write)); } else { - result->map.find(c, tvt(true)).first = - environment.write(old_value.first, value, stack, ns, merging_write); + result->map.replace( + c, + environment.write(old_value.value(), value, stack, ns, merging_write)); } result->clear_top(); @@ -249,7 +250,7 @@ sharing_ptrt #endif const irep_idt c=member_expr.get_component_name(); - shared_struct_mapt::const_find_type old_value=result->map.find(c); + auto const old_value = result->map.find(c); if(merging_write) { @@ -261,7 +262,7 @@ sharing_ptrt INVARIANT(!result->map.empty(), "If not top, map cannot be empty"); - if(!old_value.second) // component is top + if(!old_value.has_value()) // component is top { DATA_INVARIANT(result->verify(), "Structural invariants maintained"); return result; @@ -269,18 +270,18 @@ sharing_ptrt bool dummy; - result->map.find(c, tvt(true)).first = - abstract_objectt::merge(old_value.first, value, dummy); + result->map.replace( + c, abstract_objectt::merge(old_value.value(), value, dummy)); } else { - if(old_value.second) + if(old_value.has_value()) { - result->map.find(c, tvt(true)).first = value; + result->map.replace(c, value); } else { - result->map.insert(c, value, tvt(false)); + result->map.insert(c, value); } result->clear_top(); INVARIANT(!result->is_bottom(), "top != bottom"); @@ -324,14 +325,14 @@ void full_struct_abstract_objectt::output( for(const auto field : type_decl.components()) { auto value = map.find(field.get_name()); - if(value.second) + if(value.has_value()) { if(!first) { out << ", "; } out << '.' << field.get_name() << '='; - value.first->output(out, ai, ns); + static_cast(value.value())->output(out, ai, ns); first = false; } } @@ -463,7 +464,7 @@ abstract_object_pointert full_struct_abstract_objectt::visit_sub_elements( auto newval = visitor.visit(item.second); if(newval != item.second) { - result->map.find(item.first, tvt(true)).first = newval; + result->map.replace(item.first, newval); modified = true; } } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 187e5a12b28..c3769c1e3b3 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -51,7 +51,7 @@ class full_struct_abstract_objectt:public struct_abstract_objectt private: // no entry means component is top - typedef sharing_mapt + typedef sharing_mapt shared_struct_mapt; shared_struct_mapt map; diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index 93bf136d577..dc005cd829c 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -81,7 +81,7 @@ interval_from_x_lt_value(const exprt &value) return constant_interval_exprt( min_exprt(value.type()), from_integer(integer_value - 1, value.type())); else - return constant_interval_exprt().bottom(); + return constant_interval_exprt::bottom(value.type()); } static inline constant_interval_exprt @@ -92,7 +92,7 @@ interval_from_x_gt_value(const exprt &value) return constant_interval_exprt( from_integer(integer_value + 1, value.type()), max_exprt(value.type())); else - return constant_interval_exprt().bottom(); + return constant_interval_exprt::bottom(value.type()); } static inline bool represents_interval(exprt e) @@ -446,7 +446,7 @@ interval_abstract_valuet::interval_abstract_valuet( {} interval_abstract_valuet::interval_abstract_valuet( - constant_interval_exprt e, + const constant_interval_exprt e, int merge_count) : abstract_valuet(e.type(), e.is_top() || merge_count > 10, e.is_bottom()), interval(e), diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h index 56f91e50969..5e0c9f57fb8 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.h +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -26,7 +26,7 @@ class interval_abstract_valuet:public abstract_valuet explicit interval_abstract_valuet(typet t); interval_abstract_valuet(typet t, bool tp, bool bttm); - interval_abstract_valuet(constant_interval_exprt e, int merge_count); + interval_abstract_valuet(const constant_interval_exprt e, int merge_count); explicit interval_abstract_valuet( const constant_interval_exprt e); diff --git a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp index b3a7c010fb6..8ff21fd4b0a 100644 --- a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp @@ -143,7 +143,8 @@ bool interval_array_abstract_objectt::eval_index( auto index_interval = eval_and_get_as_interval(index.index(), env, ns); if(index_interval.is_single_value_interval()) { - out_index = numeric_cast_v(index_interval.get_lower()); + out_index = + numeric_cast_v(to_constant_expr(index_interval.get_lower())); return true; } return false; diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index bbaa525c2c8..e5e409a24c8 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -11,7 +11,8 @@ #include #include -#include +#include +#include /** @@ -59,12 +60,15 @@ void variable_sensitivity_dependence_domaint::eval_data_deps( * \param ns the namespace */ void variable_sensitivity_dependence_domaint::transform( + const irep_idt &function_from, locationt from, + const irep_idt &function_to, locationt to, ai_baset &ai, const namespacet &ns) { - variable_sensitivity_domaint::transform(from, to, ai, ns); + variable_sensitivity_domaint::transform( + function_from, from, function_to, to, ai, ns); variable_sensitivity_dependence_grapht *dep_graph= dynamic_cast(&ai); @@ -73,9 +77,9 @@ void variable_sensitivity_dependence_domaint::transform( // propagate control dependencies across function calls if(from->is_function_call()) { - if(from->function == to->function) + if(function_from == function_to) { - control_dependencies(from, to, *dep_graph); + control_dependencies(function_from, from, function_to, to, *dep_graph); } else { @@ -112,7 +116,7 @@ void variable_sensitivity_dependence_domaint::transform( } } else - control_dependencies(from, to, *dep_graph); + control_dependencies(function_from, from, function_to, to, *dep_graph); // Find all the data dependencies in the the 'to' expression data_dependencies(from, to, *dep_graph, ns); @@ -191,7 +195,9 @@ void variable_sensitivity_dependence_domaint::data_dependencies( } void variable_sensitivity_dependence_domaint::control_dependencies( + const irep_idt &from_function, goto_programt::const_targett from, + const irep_idt &to_function, goto_programt::const_targett to, variable_sensitivity_dependence_grapht &dep_graph) { @@ -223,7 +229,7 @@ void variable_sensitivity_dependence_domaint::control_dependencies( const goto_functionst &goto_functions=dep_graph.goto_functions; - const irep_idt id=goto_programt::get_function_id(from); + const irep_idt id = from_function; cfg_post_dominatorst &pd_tmp=dep_graph.cfg_post_dominators()[id]; goto_functionst::function_mapt::const_iterator f_it= @@ -252,13 +258,8 @@ void variable_sensitivity_dependence_domaint::control_dependencies( // we could hard-code assume and goto handling here to improve // performance - cfg_post_dominatorst::cfgt::entry_mapt::const_iterator e= - pd.cfg.entry_map.find(cd); - - assert(e!=pd.cfg.entry_map.end()); - const cfg_post_dominatorst::cfgt::nodet &m= - pd.cfg[e->second]; + pd.get_node(cd); // successors of M for(const auto &edge : m.out) @@ -582,7 +583,7 @@ jsont variable_sensitivity_dependence_domaint::output_json( } } - return graph; + return std::move(graph); } void variable_sensitivity_dependence_domaint::populate_dep_graph( diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h index 02e8f8b672c..42244737362 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -70,7 +70,9 @@ class variable_sensitivity_dependence_domaint: {} void transform( + const irep_idt &function_from, locationt from, + const irep_idt &function_to, locationt to, ai_baset &ai, const namespacet &ns) override; @@ -184,7 +186,9 @@ class variable_sensitivity_dependence_domaint: const exprt &expr, const namespacet &ns, data_depst &deps) const; void control_dependencies( + const irep_idt &from_function, goto_programt::const_targett from, + const irep_idt &to_function, goto_programt::const_targett to, variable_sensitivity_dependence_grapht &dep_graph); @@ -223,14 +227,11 @@ class variable_sensitivity_dependence_grapht: { } - void initialize(const goto_functionst &goto_functions) + void + initialize(const irep_idt &function_id, const goto_programt &goto_program) { - ait::initialize(goto_functions); - } - - void initialize(const goto_programt &goto_program) - { - ait::initialize(goto_program); + ait::initialize( + function_id, goto_program); } void finalize() diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index f1cf9206966..671df9ca15a 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -36,7 +36,9 @@ Function: variable_sensitivity_domaint::transform \*******************************************************************/ void variable_sensitivity_domaint::transform( + const irep_idt &function_from, locationt from, + const irep_idt &function_to, locationt to, ai_baset &ai, const namespacet &ns) @@ -128,7 +130,7 @@ void variable_sensitivity_domaint::transform( { // erase parameters - const irep_idt id=from->function; + const irep_idt id = function_from; const symbolt &symbol=ns.lookup(id); const code_typet &type=to_code_type(symbol.type); @@ -177,6 +179,10 @@ void variable_sensitivity_domaint::transform( // throw "other"; break; + case NO_INSTRUCTION_TYPE: + break; + case INCOMPLETE_GOTO: + break; default: throw "unrecognised instruction type"; } @@ -364,7 +370,7 @@ bool variable_sensitivity_domaint::is_top() const /// Get symbols that have been modified since this domain and other /// \param other: The domain that things may have been modified in /// \return A list of symbols whose write location is different -std::vector +std::vector variable_sensitivity_domaint::get_modified_symbols( const variable_sensitivity_domaint &other) const { @@ -452,7 +458,7 @@ void variable_sensitivity_domaint::transform_function_call( // Top any global values for(const auto &symbol : ns.get_symbol_table().symbols) { - if(!symbol.second.is_procedure_local()) + if(symbol.second.is_static_lifetime) { abstract_state.assign( symbol_exprt(symbol.first, symbol.second.type), @@ -565,9 +571,17 @@ void variable_sensitivity_domaint::merge_three_way_function_return( const variable_sensitivity_domaint &cast_function_end= static_cast(function_end); - const std::vector &modified_symbols= + const std::vector &modified_symbol_names = cast_function_start.get_modified_symbols(cast_function_end); + std::vector modified_symbols; + modified_symbols.reserve(modified_symbol_names.size()); + std::transform( + modified_symbol_names.begin(), + modified_symbol_names.end(), + std::back_inserter(modified_symbols), + [&ns](const irep_idt &id) { return ns.lookup(id).symbol_expr(); }); + abstract_state=cast_function_call.abstract_state; apply_domain(modified_symbols, cast_function_end, ns); } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 17058b6ef6d..a1c9d9e1033 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -73,7 +73,9 @@ class variable_sensitivity_domaint:public ai_domain_baset { public: virtual void transform( + const irep_idt &function_from, locationt from, + const irep_idt &function_to, locationt to, ai_baset &ai, const namespacet &ns) override; @@ -128,7 +130,7 @@ class variable_sensitivity_domaint:public ai_domain_baset bool ignore_function_call_transform(const irep_idt &function_id) const; - std::vector get_modified_symbols( + std::vector get_modified_symbols( const variable_sensitivity_domaint &other) const; void apply_domain( diff --git a/src/analyses/variable-sensitivity/write_stack.cpp b/src/analyses/variable-sensitivity/write_stack.cpp index 5183ba9da8f..82dcc3a1282 100644 --- a/src/analyses/variable-sensitivity/write_stack.cpp +++ b/src/analyses/variable-sensitivity/write_stack.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -42,7 +43,7 @@ write_stackt::write_stackt( construct_stack_to_pointer( address_of_exprt( index_exprt( - expr, from_integer(0, integer_typet()))), environment, ns); + expr, from_integer(0, size_type()))), environment, ns); } else { @@ -195,7 +196,7 @@ exprt write_stackt::to_expression() const } } address_of_exprt top_expr(access_expr); - return top_expr; + return std::move(top_expr); } /// Is the stack representing an unknown value and hence can't be written to diff --git a/unit/analyses/variable-sensitivity/abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp index d11595a565a..28da74ea945 100644 --- a/unit/analyses/variable-sensitivity/abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp @@ -6,7 +6,7 @@ \*******************************************************************/ -#include +#include #include #include diff --git a/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp index 0423411088e..12b68be058d 100644 --- a/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp @@ -7,7 +7,7 @@ \*******************************************************************/ #include -#include +#include #include #include #include @@ -16,6 +16,7 @@ #include #include #include +#include SCENARIO("merge_constant_abstract_value", 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 c3a51b50234..d49989777d8 100644 --- a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp @@ -7,7 +7,7 @@ \*******************************************************************/ #include -#include +#include #include #include #include @@ -21,6 +21,7 @@ #include #include #include +#include typedef constant_array_abstract_objectt::constant_array_pointert constant_array_abstract_object_pointert; 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 a636eea0a9f..e3f39da5a34 100644 --- a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp @@ -7,7 +7,7 @@ \*******************************************************************/ #include -#include +#include #include #include #include @@ -24,6 +24,7 @@ #include #include +#include typedef constant_array_abstract_objectt::constant_array_pointert constant_array_abstract_object_pointert; diff --git a/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp b/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp index 386664c044c..6f69dd5dce6 100644 --- a/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp +++ b/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp @@ -6,7 +6,7 @@ \*******************************************************************/ -#include +#include #include #include diff --git a/unit/analyses/variable-sensitivity/last_written_location.cpp b/unit/analyses/variable-sensitivity/last_written_location.cpp index 87dc6e87c88..506c05f613c 100644 --- a/unit/analyses/variable-sensitivity/last_written_location.cpp +++ b/unit/analyses/variable-sensitivity/last_written_location.cpp @@ -10,7 +10,7 @@ /// Unit tests for testing of correct tracking of /// last written location by objects -#include +#include #include #include @@ -24,6 +24,7 @@ #include #include #include +#include #include //#include diff --git a/unit/analyses/variable-sensitivity/write_stack.cpp b/unit/analyses/variable-sensitivity/write_stack.cpp index 116836bd70b..f300e280021 100644 --- a/unit/analyses/variable-sensitivity/write_stack.cpp +++ b/unit/analyses/variable-sensitivity/write_stack.cpp @@ -9,7 +9,7 @@ /// \file /// Unit tests for construction of write stack -#include +#include #include #include From aae01eccc67bd6f0491dd2d14bbaf9f020c28ebb Mon Sep 17 00:00:00 2001 From: xbauch Date: Fri, 16 Aug 2019 12:30:26 +0100 Subject: [PATCH 283/342] Fix interval construction when the expression to be represented is neither constant interval nor a relation. We simply return TOP interval. Includes a test that was failing. --- .../variable-sensitivity/interval_abstract_value.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index dc005cd829c..f5152ac2ed7 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -441,9 +441,12 @@ interval_abstract_valuet::interval_abstract_valuet( const abstract_environmentt &environment, const namespacet &ns) : interval_abstract_valuet( - represents_interval(e) ? make_interval_expr(e) - : interval_from_relation(e)) -{} + represents_interval(e) + ? make_interval_expr(e) + : (e.operands().size() == 2 ? interval_from_relation(e) + : constant_interval_exprt(e.type()))) +{ +} interval_abstract_valuet::interval_abstract_valuet( const constant_interval_exprt e, From 38daf40192385871286e86c4ca2d55ccbf84fce0 Mon Sep 17 00:00:00 2001 From: Chris Ryder Date: Tue, 12 Nov 2019 16:35:40 +0000 Subject: [PATCH 284/342] Support interval expressions containing ?: operations --- .../main.c | 10 ++++++ .../test.desc | 3 +- .../interval_abstract_value.cpp | 33 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/main.c index c102801ea36..10b6f41e7fc 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/main.c +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/main.c @@ -1,5 +1,7 @@ #include +extern int x; + int main(void) { bool b1; @@ -8,5 +10,13 @@ int main(void) b1 = true; b2 = !b1; + bool b3; + if(x) + b3 = true; + else + b3 = false; + + int i = b3 ? 10 : 20; + return 0; } diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc index ba22ca83685..446f664a76c 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc @@ -4,5 +4,6 @@ main.c ^EXIT=0$ ^SIGNAL=0$ main::1::b1 \(\) -> \[1, 1\] @ \[2\] -main::1::b2 \(\) -> \[0, 0\] +main::1::b2 \(\) -> \[0, 0\] @ \[3\] +main::1::i \(\) -> \[A\, 14\] @ \[11\] -- diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index f5152ac2ed7..67f85da49ca 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -307,6 +307,39 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( return environment.abstract_object_factory(type, interval, ns); } + else if(num_operands == 3) + { + if(expr.id() == ID_if) + { + const constant_interval_exprt &condition_interval = interval_operands[0]->interval; + const constant_interval_exprt &true_interval = interval_operands[1]->interval; + const constant_interval_exprt &false_interval = interval_operands[2]->interval; + + // Check the value of the condition interval + if(condition_interval.is_definitely_false().is_unknown()) { + // Value of the condition is both true and false, so + // combine the intervals of both the true and false expressions + return environment.abstract_object_factory( + type, + constant_interval_exprt( + constant_interval_exprt::get_min(true_interval.get_lower(), false_interval.get_lower()), + constant_interval_exprt::get_max(true_interval.get_upper(), false_interval.get_upper())), + ns); + } + if(condition_interval.is_definitely_false().is_true()) { + // The condition is definitely false, so return only + // the interval from the 'false' expression + return environment.abstract_object_factory( + false_interval.type(), false_interval, ns); + } + if(condition_interval.is_definitely_true().is_true()) { + // The condition is definitely true, so return only + // the interval from the 'true' expression + return environment.abstract_object_factory( + true_interval.type(), true_interval, ns); + } + } + } return environment.abstract_object_factory(type, ns, true); } From 913d90edd974cd12abcbe114032f561df57ae2ea Mon Sep 17 00:00:00 2001 From: Owen Date: Wed, 11 Mar 2020 15:41:49 +0000 Subject: [PATCH 285/342] Extend the interface with hashing and equality for unordered-sets. --- .../variable-sensitivity/abstract_object.h | 31 +++++++++++++++++++ .../constant_abstract_value.h | 12 +++++++ 2 files changed, 43 insertions(+) diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 0ad74b8a19b..7b0ed4188f0 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -224,6 +224,16 @@ class abstract_objectt:public std::enable_shared_from_this const abstract_object_visitort &visitor) const { return shared_from_this(); } + virtual size_t internal_hash() const + { + return std::hash{}(shared_from_this()); + } + + virtual bool internal_equality(const abstract_object_pointert &other) const + { + return shared_from_this() == other; + } + private: // To enforce copy-on-write these are private and have read-only accessors typet t; @@ -360,4 +370,25 @@ bool abstract_objectt::merge_shared_maps( return modified; } +struct abstract_hashert +{ + typedef abstract_object_pointert argument_typet; + typedef std::size_t result_typet; + result_typet operator()(argument_typet const &s) const noexcept + { + return s->internal_hash(); + } +}; + +struct abstract_equalert +{ + typedef abstract_object_pointert argument_typet; + typedef std::size_t result_typet; + bool operator()(argument_typet const &left, argument_typet const &right) const + noexcept + { + return left->internal_equality(right); + } +}; + #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 fddc6843dd1..97bd230005c 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -47,6 +47,18 @@ class constant_abstract_valuet:public abstract_valuet const abstract_environmentt &env, const namespacet& ns) const override; + size_t internal_hash() const override + { + return std::hash{}(value.pretty()); + } + + bool internal_equality(const abstract_object_pointert &other) const override + { + auto cast_other = + std::dynamic_pointer_cast(other); + return cast_other && value == cast_other->value; + } + protected: CLONE virtual abstract_object_pointert merge( From 6297b1c9f5e0828f9d5cbb9aad2a1d91ee262caa Mon Sep 17 00:00:00 2001 From: Owen Date: Wed, 11 Mar 2020 15:05:52 +0000 Subject: [PATCH 286/342] Implement value sets as a new abstract object. --- src/analyses/Makefile | 1 + .../abstract_enviroment.cpp | 7 +- .../constant_pointer_abstract_object.cpp | 22 +- .../context_abstract_object.cpp | 4 + .../context_abstract_object.h | 2 + .../interval_abstract_value.cpp | 27 +- .../value_set_abstract_object.cpp | 305 ++++++++++++++++++ .../value_set_abstract_object.h | 228 +++++++++++++ .../variable_sensitivity_domain.cpp | 8 +- .../variable_sensitivity_object_factory.cpp | 12 + .../variable_sensitivity_object_factory.h | 20 +- .../write_stack_entry.cpp | 2 +- 12 files changed, 617 insertions(+), 21 deletions(-) create mode 100644 src/analyses/variable-sensitivity/value_set_abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/value_set_abstract_object.h diff --git a/src/analyses/Makefile b/src/analyses/Makefile index 64249f0c8bc..bbdcd71dfa7 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -51,6 +51,7 @@ SRC = ai.cpp \ variable-sensitivity/write_stack.cpp \ variable-sensitivity/write_stack_entry.cpp \ variable-sensitivity/data_dependency_context.cpp \ + variable-sensitivity/value_set_abstract_object.cpp \ variable-sensitivity/variable_sensitivity_dependence_graph.cpp \ variable-sensitivity/interval_abstract_value.cpp \ variable-sensitivity/interval_array_abstract_object.cpp \ diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 32dbefc5de0..c4e8fc99887 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -247,6 +247,7 @@ bool abstract_environmentt::assign( if(final_value != lhs_value) { + CHECK_RETURN(!symbol_expr.get_identifier().empty()); map.insert_or_replace(symbol_expr.get_identifier(), final_value); } } @@ -402,7 +403,7 @@ Function: abstract_environmentt::abstract_object_factory abstract_object_pointert abstract_environmentt::abstract_object_factory( const typet &type, const namespacet &ns, bool top, bool bottom) const { - exprt empty_constant_expr=exprt(); + exprt empty_constant_expr = nil_exprt(); return abstract_object_factory( type, top, bottom, empty_constant_expr, *this, ns); } @@ -732,7 +733,10 @@ abstract_environmentt::modified_symbols( if (second_entry.has_value()) { if(second_entry.value().get()->has_been_modified(entry.second)) + { + CHECK_RETURN(!entry.first.empty()); symbols_diff.push_back(entry.first); + } } } @@ -742,6 +746,7 @@ abstract_environmentt::modified_symbols( const auto &second_entry = first.map.find(entry.first); if (!second_entry.has_value()) { + CHECK_RETURN(!entry.first.empty()); symbols_diff.push_back(entry.first); } } diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index c6a5077ed9c..e2e2796738f 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -238,14 +238,28 @@ void constant_pointer_abstract_objectt::output( const exprt &value=value_stack.to_expression(); 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 auto &addressee = to_address_of_expr(value).object(); + if(addressee.id() == ID_symbol) { - const symbol_exprt &symbol_pointed_to( - to_symbol_expr(address_expr.object())); + const symbol_exprt &symbol_pointed_to(to_symbol_expr(addressee)); out << symbol_pointed_to.get_identifier(); } + else if(addressee.id() == ID_index) + { + auto const &array_index = to_index_expr(addressee); + auto const &array = array_index.array(); + if(array.id() == ID_symbol) + { + auto const &array_symbol = to_symbol_expr(array); + out << array_symbol.get_identifier() << "["; + if(array_index.index().id() == ID_constant) + out << to_constant_expr(array_index.index()).get_value(); + else + out << "?"; + out << "]"; + } + } } out << ")"; diff --git a/src/analyses/variable-sensitivity/context_abstract_object.cpp b/src/analyses/variable-sensitivity/context_abstract_object.cpp index 91ea958c352..b89bae9842b 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/context_abstract_object.cpp @@ -8,6 +8,10 @@ #include "context_abstract_object.h" +abstract_object_pointert context_abstract_objectt::get_child() const +{ + return child_abstract_object; +} void context_abstract_objectt::set_child( const abstract_object_pointert &child) diff --git a/src/analyses/variable-sensitivity/context_abstract_object.h b/src/analyses/variable-sensitivity/context_abstract_object.h index a9fff3029a0..d1db479670e 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.h +++ b/src/analyses/variable-sensitivity/context_abstract_object.h @@ -90,6 +90,8 @@ class context_abstract_objectt: public abstract_objectt const abstract_environmentt &env, const namespacet &ns) const override; + abstract_object_pointert get_child() const; + protected: CLONE diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index 67f85da49ca..0cf9bdce46a 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -14,6 +14,7 @@ #include "abstract_enviroment.h" +#include "context_abstract_object.h" #include "interval_abstract_value.h" static inline exprt look_through_casts(exprt e) @@ -231,9 +232,31 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( if(constant_interval_exprt::is_int(op->type())) { - const auto ivop = environment.abstract_object_factory(op->type(), op->to_constant(), ns); - iav = std::dynamic_pointer_cast(ivop); + const auto op_as_constant = op->to_constant(); + if(op_as_constant.is_nil()) + { + auto top_object = + environment.abstract_object_factory(expr.type(), ns, true); + auto top_context_object = + std::dynamic_pointer_cast( + top_object); + CHECK_RETURN(top_context_object); + return top_context_object->get_child(); + } + const auto ivop = + environment.abstract_object_factory(op->type(), op_as_constant, ns); + const auto ivop_context = + std::dynamic_pointer_cast(ivop); + if(ivop_context) + { + iav = std::dynamic_pointer_cast( + ivop_context->get_child()); + } + else + iav = std::dynamic_pointer_cast(ivop); } + CHECK_RETURN( + !std::dynamic_pointer_cast(iav)); if(!iav) { diff --git a/src/analyses/variable-sensitivity/value_set_abstract_object.cpp b/src/analyses/variable-sensitivity/value_set_abstract_object.cpp new file mode 100644 index 00000000000..9a64a17aae6 --- /dev/null +++ b/src/analyses/variable-sensitivity/value_set_abstract_object.cpp @@ -0,0 +1,305 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: diffblue + +\*******************************************************************/ + +/// \file +/// Value Set Abstract Object + +#include +#include +#include +#include +#include +#include +#include +#include + +value_set_abstract_objectt::value_set_abstract_objectt(const typet &type) + : abstract_valuet(type), my_type(type_to_abstract_type(type)) +{ + switch(my_type) + { + case abstract_typet::POINTER: + values.insert(std::make_shared(type)); + break; + case abstract_typet::CONSTANT: + values.insert(std::make_shared(type)); + break; + case abstract_typet::UNSUPPORTED: + UNREACHABLE; + } + verify(); +} + +value_set_abstract_objectt::value_set_abstract_objectt( + const typet &type, + bool top, + bool bottom) + : abstract_valuet(type, top, bottom), my_type(type_to_abstract_type(type)) +{ + switch(my_type) + { + case abstract_typet::POINTER: + values.insert( + std::make_shared(type, top, bottom)); + break; + case abstract_typet::CONSTANT: + values.insert( + std::make_shared(type, top, bottom)); + break; + case abstract_typet::UNSUPPORTED: + UNREACHABLE; + } + verify(); +} + +value_set_abstract_objectt::value_set_abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) + : abstract_valuet(expr.type(), false, false), + my_type(type_to_abstract_type(expr.type())) +{ + switch(my_type) + { + case abstract_typet::POINTER: + values.insert(std::make_shared( + expr, environment, ns)); + break; + case abstract_typet::CONSTANT: + values.insert( + std::make_shared(expr, environment, ns)); + break; + case abstract_typet::UNSUPPORTED: + UNREACHABLE; + } + verify(); +} + +abstract_object_pointert value_set_abstract_objectt::expression_transform( + const exprt &expr, + const std::vector &operands, + const abstract_environmentt &environment, + const namespacet &ns) const +{ + std::size_t num_operands = expr.operands().size(); + PRECONDITION(operands.size() == num_operands); + + std::vector collective_operands; + collective_operands.reserve(num_operands); + for(const auto &op : operands) + { + auto vsab = std::dynamic_pointer_cast( + maybe_unwrap_context(op)); + INVARIANT(vsab, "should be a value set abstract object"); + collective_operands.push_back(vsab->get_values()); + } + + abstract_object_sett resulting_objects; + for_each_comb( + collective_operands, + [&resulting_objects, this, &expr, &environment, &ns]( + const std::vector &ops) { + resulting_objects.insert( + (*values.begin())->expression_transform(expr, ops, environment, ns)); + }); + + return resolve_new_values(resulting_objects); +} + +abstract_object_pointert value_set_abstract_objectt::read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const +{ + abstract_object_sett new_values; + for(const auto &st_value : values) + new_values.insert(st_value->read(env, specifier, ns)); + + return resolve_new_values(new_values); +} + +abstract_object_pointert value_set_abstract_objectt::write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const +{ + abstract_object_sett new_values; + for(const auto &st_value : values) + { + new_values.insert( + st_value->write(environment, ns, stack, specifier, value, merging_write)); + } + return resolve_new_values(new_values); +} + +abstract_object_pointert value_set_abstract_objectt::resolve_new_values( + const abstract_object_sett &new_values) const +{ + PRECONDITION(!new_values.empty()); + + if(new_values == values) + return shared_from_this(); + + abstract_object_sett unwrapped_values; + for(auto const &value : new_values) + { + unwrapped_values.insert( + maybe_extract_single_value(maybe_unwrap_context(value))); + } + + abstract_typet new_type = get_type(*unwrapped_values.begin()); + if( + unwrapped_values.size() > max_value_set_size && + new_type == abstract_typet::CONSTANT) + { + return to_interval(unwrapped_values); + } + if(unwrapped_values.size() == 1 && new_type == abstract_typet::UNSUPPORTED) + { + return (*unwrapped_values.begin()); + } + + const auto &result = + std::dynamic_pointer_cast(mutable_clone()); + + if( + unwrapped_values.size() > max_value_set_size || + new_type == abstract_typet::UNSUPPORTED) + { + result->make_top(); + } + else + { + result->set_values(unwrapped_values); + } + return result; +} + +abstract_object_pointert +value_set_abstract_objectt::merge(abstract_object_pointert other) const +{ + auto cast_other = + std::dynamic_pointer_cast(other); + if(cast_other && cast_other->get_my_type() == get_my_type()) + { + auto union_values = values; + union_values.insert( + cast_other->get_values().begin(), cast_other->get_values().end()); + return resolve_new_values(union_values); + } + else + return abstract_objectt::merge(other); +} + +abstract_object_pointert value_set_abstract_objectt::to_interval( + const abstract_object_sett &other_values) const +{ + PRECONDITION(!other_values.empty()); + if(get_type(*other_values.begin()) == abstract_typet::POINTER) + return std::make_shared( + type(), true, false); + PRECONDITION(get_type(*other_values.begin()) == abstract_typet::CONSTANT); + + exprt lower_expr = (*other_values.begin())->to_constant(); + exprt upper_expr = (*other_values.begin())->to_constant(); + for(const auto &value : other_values) + { + const auto &value_expr = value->to_constant(); + lower_expr = constant_interval_exprt::get_min(lower_expr, value_expr); + upper_expr = constant_interval_exprt::get_min(upper_expr, value_expr); + } + return std::make_shared( + constant_interval_exprt(lower_expr, upper_expr)); +} + +bool value_set_abstract_objectt::verify() const +{ + CHECK_RETURN(my_type != abstract_typet::UNSUPPORTED); + for(const auto &value : values) + { + CHECK_RETURN( + !std::dynamic_pointer_cast(value)); + CHECK_RETURN(get_type(value) == my_type); + } + return true; +} + +value_set_abstract_objectt::abstract_typet +value_set_abstract_objectt::get_type(const abstract_object_pointert &other) +{ + PRECONDITION( + !std::dynamic_pointer_cast(other)); + PRECONDITION(!std::dynamic_pointer_cast(other)); + PRECONDITION( + !std::dynamic_pointer_cast(other)); + PRECONDITION(!std::dynamic_pointer_cast(other)); + PRECONDITION( + !std::dynamic_pointer_cast(other)); + + if(std::dynamic_pointer_cast(other)) + return abstract_typet::POINTER; + if(std::dynamic_pointer_cast(other)) + return abstract_typet::CONSTANT; + UNREACHABLE; + return abstract_typet::UNSUPPORTED; +} + +abstract_object_pointert value_set_abstract_objectt::maybe_extract_single_value( + const abstract_object_pointert &maybe_singleton) +{ + auto const &value_as_set = + std::dynamic_pointer_cast( + maybe_singleton); + if(value_as_set) + { + PRECONDITION(value_as_set->get_values().size() == 1); + PRECONDITION(!std::dynamic_pointer_cast( + *value_as_set->get_values().begin())); + + return *value_as_set->get_values().begin(); + } + else + return maybe_singleton; +} + +abstract_object_pointert value_set_abstract_objectt::maybe_unwrap_context( + const abstract_object_pointert &maybe_wrapped) +{ + auto const &context_value = + std::dynamic_pointer_cast(maybe_wrapped); + + return context_value ? context_value->unwrap_context() : maybe_wrapped; +} + +void value_set_abstract_objectt::output( + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const +{ + if(is_top()) + { + out << "TOP"; + } + else if(is_bottom()) + { + out << "BOTTOM"; + } + else + { + out << "value-set-begin: "; + for(auto const &value : values) + { + value->output(out, ai, ns); + out << ", "; + } + out << ":value-set-end"; + } +} diff --git a/src/analyses/variable-sensitivity/value_set_abstract_object.h b/src/analyses/variable-sensitivity/value_set_abstract_object.h new file mode 100644 index 00000000000..a614dbc9e15 --- /dev/null +++ b/src/analyses/variable-sensitivity/value_set_abstract_object.h @@ -0,0 +1,228 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity + + Author: diffblue + +\*******************************************************************/ + +/// \file +/// Value Set Abstract Object + +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_ABSTRACT_OBJECT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_ABSTRACT_OBJECT_H + +#include + +#include + +class value_set_abstract_objectt : public abstract_valuet +{ +public: + using abstract_object_sett = std::unordered_set< + abstract_object_pointert, + abstract_hashert, + abstract_equalert>; + + /// \copydoc abstract_objectt::abstract_objectt(const typet&) + explicit value_set_abstract_objectt(const typet &type); + + /// \copydoc abstract_objectt::abstract_objectt(const typet &, bool, bool) + value_set_abstract_objectt(const typet &type, bool top, bool bottom); + + value_set_abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); + + /// \copydoc abstract_objectt::to_constant + exprt to_constant() const override + { + verify(); + return values.size() == 1 ? (*values.begin())->to_constant() + : abstract_objectt::to_constant(); + } + + /// \copydoc abstract_objectt::expression_transform + /// + /// Transforms the \p expr for every combination of \p operands (since these + /// can be value-sets as well). + abstract_object_pointert expression_transform( + const exprt &expr, + const std::vector &operands, + const abstract_environmentt &environment, + const namespacet &ns) const override; + + /// Getter for the set of stored abstract objects. + /// \return the values represented by this abstract object + const abstract_object_sett &get_values() const + { + return values; + } + + /// Setter for updating the stored values + /// \param other_values: the new (non-empty) set of values + void set_values(const abstract_object_sett &other_values) + { + PRECONDITION(!other_values.empty()); + my_type = get_type(*other_values.begin()); + values = other_values; + verify(); + } + + /// Distinguish the type of abstract objects stored in this value-set. + enum class abstract_typet + { + CONSTANT, + POINTER, + UNSUPPORTED + }; + + /// Getter for the type of stored values + /// \return the abstract-type stored here + abstract_typet get_my_type() const + { + return my_type; + } + + /// The threshold size for value-sets: past this threshold the object is + /// either converted to interval or marked as `top`. + static const size_t max_value_set_size = 10; + + /// \copydoc abstract_objectt::read + /// + /// Delegate reading to stored values. + abstract_object_pointert read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const override; + + /// \copydoc abstract_objectt::write + /// + /// Delegate writing to stored values. + abstract_object_pointert write( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const exprt &specifier, + const abstract_object_pointert value, + bool merging_write) const override; + + /// Enforce casting to interval. + /// \return the stored values abstracted to an interval + abstract_object_pointert get_as_interval() const + { + return to_interval(values); + } + + void output(std::ostream &out, const ai_baset &ai, const namespacet &ns) + const override; + +protected: + CLONE + + /// Update the set of stored values to \p new_values. Build a new abstract + /// object of the right type if necessary. + /// \param new_values: potentially new set of values + /// \return the abstract object representing \p new_values (either 'this' or + /// something new) + abstract_object_pointert + resolve_new_values(const abstract_object_sett &new_values) const; + + /// \copydoc abstract_object::merge + abstract_object_pointert merge(abstract_object_pointert other) const override; + +private: + // data + abstract_typet my_type; + abstract_object_sett values; + + /// Cast the set of values \p other_values to an interval. + /// \param other_values: the value-set to be abstracted into an interval + /// \return the interval-abstract-object containing \p other_values + abstract_object_pointert + to_interval(const abstract_object_sett &other_values) const; + + /// \copydoc abstract_objectt::verify + bool verify() const override; + + /// Recursively construct a combination \p sub_con from \p super_con and once + /// constructed call \p f. + /// \param super_con: vector of some containers storing the values + /// \param sub_con: the one combination being currently constructed + /// \param f: callable with side-effects + template + void apply_comb( + const std::vector &super_con, + std::vector &sub_con, + F f) const + { + size_t n = sub_con.size(); + if(n == super_con.size()) + f(sub_con); + else + { + for(const auto &value : super_con[n]) + { + sub_con.push_back(value); + apply_comb(super_con, sub_con, f); + sub_con.pop_back(); + } + } + } + + /// Call the function \p f on every combination of elements in \p super_con. + /// Hence the arity of \p f is `super_con.size()`. <{1,2},{1},{1,2,3}> -> + /// f(1,1,1), f(1,1,2), f(1,1,3), f(2,1,1), f(2,1,2), f(2,1,3). + /// \param super_con: vector of some containers storing the values + /// \param f: callable with side-effects + template + void for_each_comb(const std::vector &super_con, F f) const + { + std::vector sub_con; + apply_comb(super_con, sub_con, f); + } + + /// Determine abstract-type of an abstract object \p other. + /// \param other: the abstract object to get the type of + /// \return the abstract-type of \p other + static abstract_typet get_type(const abstract_object_pointert &other); + + /// Determine abstract-type of an expression-type \p type. + /// \param type: the expression type to get the abstract-type of + /// \return the abstract-type of \p type + static abstract_typet type_to_abstract_type(const typet &type) + { + if(type.id() == ID_pointer) + { + return abstract_typet::POINTER; + } + else if( + type.id() == ID_signedbv || type.id() == ID_unsignedbv || + type.id() == ID_fixedbv || type.id() == ID_c_bool || + type.id() == ID_bool || type.id() == ID_integer || + type.id() == ID_c_bit_field || type.id() == ID_floatbv) + { + return abstract_typet::CONSTANT; + } + else + { + return abstract_typet::UNSUPPORTED; + } + } + + /// Helper for converting singleton value sets into its only value. + /// \p maybe_singleton: either a set of abstract values or a single value + /// \return an abstract value without context + static abstract_object_pointert + maybe_extract_single_value(const abstract_object_pointert &maybe_singleton); + + /// Helper for converting context objects into its abstract-value children + /// \p maybe_wrapped: either an abstract value (or a set of those) or one + /// wrapped in a context + /// \return an abstract value without context (though it might be as set) + static abstract_object_pointert + maybe_unwrap_context(const abstract_object_pointert &maybe_wrapped); +}; + +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 671df9ca15a..cab6594900c 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -81,10 +81,10 @@ void variable_sensitivity_domaint::transform( { // TODO : check return values const code_assignt &inst = to_code_assign(instruction.code); - - const abstract_objectt::locationst write_location={ from }; - abstract_object_pointert rhs =abstract_state.eval(inst.rhs(), ns) - ->update_location_context(write_location, true); + const abstract_objectt::locationst write_location = {from}; + abstract_object_pointert rhs = + abstract_state.eval(inst.rhs(), ns) + ->update_location_context(write_location, true); abstract_state.assign(inst.lhs(), rhs, ns); } break; diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 36176b06aad..7e83ad13d5a 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -59,6 +59,14 @@ variable_sensitivity_object_factoryt::ABSTRACT_OBJECT_TYPET { abstract_object_type=UNION_INSENSITIVE; } + if( + has_value_set_flag && + (abstract_object_type == INTERVAL || abstract_object_type == CONSTANT || + abstract_object_type == POINTER_INSENSITIVE || + abstract_object_type == POINTER_SENSITIVE)) + { + abstract_object_type = VALUE_SET; + } return abstract_object_type; } @@ -137,6 +145,9 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: case TWO_VALUE: return initialize_abstract_object( followed_type, top, bottom, e, environment, ns); + case VALUE_SET: + return initialize_abstract_object( + followed_type, top, bottom, e, environment, ns); default: UNREACHABLE; return initialize_abstract_object( @@ -168,5 +179,6 @@ void variable_sensitivity_object_factoryt::set_options(const optionst &options) has_data_dependencies_context_flag= options.get_bool_option("data-dependencies"); has_interval=options.get_bool_option("interval"); + has_value_set_flag = options.get_bool_option("value-set"); 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 c2c0f40f576..758fd68f1cb 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -8,21 +8,21 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_OBJECT_FACTORY_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_OBJECT_FACTORY_H -#include -#include -#include -#include #include +#include #include #include +#include +#include #include +#include +#include +#include #include -#include +#include #include -#include -#include #include - +#include class variable_sensitivity_object_factoryt { @@ -56,7 +56,8 @@ class variable_sensitivity_object_factoryt STRUCT_SENSITIVE, STRUCT_INSENSITIVE, // TODO: plug in UNION_SENSITIVE HERE - UNION_INSENSITIVE + UNION_INSENSITIVE, + VALUE_SET }; ABSTRACT_OBJECT_TYPET get_abstract_object_type(const typet type); template @@ -81,6 +82,7 @@ class variable_sensitivity_object_factoryt bool has_pointers_flag; bool has_last_written_location_context_flag; bool has_data_dependencies_context_flag; + bool has_value_set_flag; bool has_interval; bool initialized; }; diff --git a/src/analyses/variable-sensitivity/write_stack_entry.cpp b/src/analyses/variable-sensitivity/write_stack_entry.cpp index 0523522a1eb..9f0f0407bf6 100644 --- a/src/analyses/variable-sensitivity/write_stack_entry.cpp +++ b/src/analyses/variable-sensitivity/write_stack_entry.cpp @@ -61,7 +61,7 @@ exprt offset_entryt::get_access_expr() const // This constructs a something that is basicallyt '(null)[offset])' // meaning that we don't know what the type is at this point, as the // array part will be filled in later. - return index_exprt(exprt(), offset->to_constant()); + return index_exprt(nil_exprt(), offset->to_constant()); } /// For an offset entry, the type of the access expression can only be From 855cc06ba5b4b3abef62069f296f2e541515809e Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 12 Mar 2020 15:17:38 +0000 Subject: [PATCH 287/342] If there is no context to wrap - don't wrap the objects There is no value in wrapping an object with no additional information, and there is currently some problems with wrapping --- .../variable_sensitivity_object_factory.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index 758fd68f1cb..518a8ac63c2 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -125,9 +125,19 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: abstract_object_classt, write_location_contextt>( type, top, bottom, e, enviroment, ns); else - return initialize_context_abstract_object< - abstract_object_classt, context_abstract_objectt>( - type, top, bottom, e, enviroment, ns); + { + if(top || bottom) + { + return abstract_object_pointert( + new abstract_object_classt(type, top, bottom)); + } + else + { + PRECONDITION(type == ns.follow(e.type())); + return abstract_object_pointert( + new abstract_object_classt(e, enviroment, ns)); + } + } } template From 67f049cc606d3e94d768473d2100fbca461e8722 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 12 Mar 2020 15:19:49 +0000 Subject: [PATCH 288/342] Only enable location context if value set is turned off There is currently some inconsistency between how the value set and the interval domains handle wrapping. Specifically, the value set returns an unwrapped object when eval'd, whereas the interval domain returns a wrapped object. Since the rest of the code is compatible with the interval suggestion, we temporarily disable wrapping if using value set --- .../variable_sensitivity_object_factory.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 7e83ad13d5a..cf817eac0e0 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -175,7 +175,8 @@ void variable_sensitivity_object_factoryt::set_options(const optionst &options) has_structs_flag=options.get_bool_option("structs"); has_arrays_flag=options.get_bool_option("arrays"); has_pointers_flag=options.get_bool_option("pointers"); - has_last_written_location_context_flag=true; // For efficency of 3way merge + has_last_written_location_context_flag = !options.get_bool_option( + "value-set"); // For efficency of 3way merge (note does not work with value set) has_data_dependencies_context_flag= options.get_bool_option("data-dependencies"); has_interval=options.get_bool_option("interval"); From bd84b4560a8ddd483c499ef7bdaa81eca61ff2ae Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 12 Mar 2020 15:23:44 +0000 Subject: [PATCH 289/342] Produce an error if value set is used with a context tracking argument --- .../variable_sensitivity_object_factory.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index cf817eac0e0..17576aba5e4 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -171,6 +171,16 @@ Function: variable_sensitivity_object_factoryt::set_options void variable_sensitivity_object_factoryt::set_options(const optionst &options) { + if( + options.get_bool_option("value-set") && + options.get_bool_option("data-dependencies")) + { + throw invalid_command_line_argument_exceptiont{ + "Value set is not currently supported with data dependency analysis", + "--value-set --data-dependencies", + "--data-dependencies"}; + } + has_variables_flag=options.get_bool_option("variable"); has_structs_flag=options.get_bool_option("structs"); has_arrays_flag=options.get_bool_option("arrays"); From d569f4ee6596bf56e4709b69f1686523420b5d5c Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 12 Mar 2020 15:42:38 +0000 Subject: [PATCH 290/342] Remove unusued boolean flag The variable sensitivity domain is always on, if we're using the variable sensitivity domain object factory --- .../variable-sensitivity/variable_sensitivity_object_factory.cpp | 1 - .../variable-sensitivity/variable_sensitivity_object_factory.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 17576aba5e4..e39ca0d61f8 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -181,7 +181,6 @@ void variable_sensitivity_object_factoryt::set_options(const optionst &options) "--data-dependencies"}; } - 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 index 518a8ac63c2..a900600c3f9 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -76,7 +76,6 @@ class variable_sensitivity_object_factoryt const exprt &e, const abstract_environmentt &enviroment, const namespacet &ns); - bool has_variables_flag; bool has_structs_flag; bool has_arrays_flag; bool has_pointers_flag; From 405eafb37ceb2629a5ddf9745f1cd12b439a581e Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 12 Mar 2020 16:06:50 +0000 Subject: [PATCH 291/342] Remove the way to set configuration options using only optionst --- .../variable_sensitivity_object_factory.cpp | 33 ++++------- .../variable_sensitivity_object_factory.h | 59 ++++++++++++++++++- .../constant_array_abstract_object/merge.cpp | 3 +- .../full_struct_abstract_object/merge.cpp | 3 +- .../last_written_location.cpp | 4 +- 5 files changed, 77 insertions(+), 25 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index e39ca0d61f8..3f6be1d8a3a 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -169,26 +169,17 @@ Function: variable_sensitivity_object_factoryt::set_options \*******************************************************************/ -void variable_sensitivity_object_factoryt::set_options(const optionst &options) +void variable_sensitivity_object_factoryt::set_options( + const vsd_configt &options) { - if( - options.get_bool_option("value-set") && - options.get_bool_option("data-dependencies")) - { - throw invalid_command_line_argument_exceptiont{ - "Value set is not currently supported with data dependency analysis", - "--value-set --data-dependencies", - "--data-dependencies"}; - } - - has_structs_flag=options.get_bool_option("structs"); - has_arrays_flag=options.get_bool_option("arrays"); - has_pointers_flag=options.get_bool_option("pointers"); - has_last_written_location_context_flag = !options.get_bool_option( - "value-set"); // For efficency of 3way merge (note does not work with value set) - has_data_dependencies_context_flag= - options.get_bool_option("data-dependencies"); - has_interval=options.get_bool_option("interval"); - has_value_set_flag = options.get_bool_option("value-set"); - initialized=true; + has_structs_flag = options.primitive_sensitivity.struct_sensitivity; + has_arrays_flag = options.primitive_sensitivity.array_sensitivity; + has_pointers_flag = options.primitive_sensitivity.pointer_sensitivity; + has_last_written_location_context_flag = + options.context_tracking.last_write_context; + has_data_dependencies_context_flag = + options.context_tracking.last_write_context; + has_interval = options.advanced_sensitivities.intervals; + has_value_set_flag = options.advanced_sensitivities.value_set; + 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 a900600c3f9..b475bbb35af 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -24,6 +24,63 @@ #include #include +struct vsd_configt +{ + struct + { + bool struct_sensitivity; + bool array_sensitivity; + bool pointer_sensitivity; + } primitive_sensitivity; + + struct + { + bool data_dependency_context; + bool last_write_context; + } context_tracking; + + struct + { + bool intervals; + bool value_set; + } advanced_sensitivities; + + static vsd_configt from_options(const optionst &options) + { + vsd_configt config{}; + + if( + options.get_bool_option("value-set") && + options.get_bool_option("data-dependencies")) + { + throw invalid_command_line_argument_exceptiont{ + "Value set is not currently supported with data dependency analysis", + "--value-set --data-dependencies", + "--data-dependencies"}; + } + + config.primitive_sensitivity.struct_sensitivity = + options.get_bool_option("structs"); + config.primitive_sensitivity.array_sensitivity = + options.get_bool_option("arrays"); + config.primitive_sensitivity.pointer_sensitivity = + options.get_bool_option("pointers"); + + // This should always be on (for efficeny with 3-way merge) + // Does not work with value set + config.context_tracking.last_write_context = + !options.get_bool_option("value-set"); + config.context_tracking.data_dependency_context = + options.get_bool_option("data-dependencies"); + config.advanced_sensitivities.intervals = + options.get_bool_option("interval"); + config.advanced_sensitivities.value_set = + options.get_bool_option("value-set"); + + return config; + } +}; + class variable_sensitivity_object_factoryt { public: @@ -38,7 +95,7 @@ class variable_sensitivity_object_factoryt const exprt &e, const abstract_environmentt &environment, const namespacet &ns); - void set_options(const optionst &options); + void set_options(const vsd_configt &options); private: variable_sensitivity_object_factoryt():initialized(false) 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 d49989777d8..ebdc51b6a48 100644 --- a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp @@ -107,7 +107,8 @@ SCENARIO("merge_constant_array_abstract_object", options.set_option("pointers", true); options.set_option("arrays", true); options.set_option("structs", true); - variable_sensitivity_object_factoryt::instance().set_options(options); + variable_sensitivity_object_factoryt::instance().set_options( + vsd_configt::from_options(options)); array_utilt util(enviroment, ns); 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 e3f39da5a34..520e19e1d63 100644 --- a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp @@ -138,7 +138,8 @@ SCENARIO("merge_full_struct_abstract_object", options.set_option("pointers", true); options.set_option("arrays", true); options.set_option("structs", true); - variable_sensitivity_object_factoryt::instance().set_options(options); + variable_sensitivity_object_factoryt::instance().set_options( + vsd_configt::from_options(options)); struct_utilt util(enviroment, ns); diff --git a/unit/analyses/variable-sensitivity/last_written_location.cpp b/unit/analyses/variable-sensitivity/last_written_location.cpp index 506c05f613c..4bec5ae800c 100644 --- a/unit/analyses/variable-sensitivity/last_written_location.cpp +++ b/unit/analyses/variable-sensitivity/last_written_location.cpp @@ -52,7 +52,9 @@ SCENARIO("Constructing two environments to make sure we correctly identify modif symbol_table.add(second_sym); namespacet ns(symbol_table); - variable_sensitivity_object_factoryt::instance().set_options(optionst{}); + optionst options; + variable_sensitivity_object_factoryt::instance().set_options( + vsd_configt::from_options(options)); WHEN("The identifiers get inserted into two environments") { From 7ff4dc8e44f410f2abc5e2ebd98a890886389f7d Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 12 Mar 2020 16:15:13 +0000 Subject: [PATCH 292/342] Introduce some sensible config defaults --- .../variable_sensitivity_object_factory.h | 31 +++++++++++++++++++ .../constant_array_abstract_object/merge.cpp | 6 +--- .../full_struct_abstract_object/merge.cpp | 6 +--- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index b475bbb35af..ee61fb79ca6 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -79,6 +79,37 @@ struct vsd_configt return config; } + + static vsd_configt constant_domain() + { + vsd_configt config{}; + config.primitive_sensitivity.pointer_sensitivity = true; + config.primitive_sensitivity.array_sensitivity = true; + config.primitive_sensitivity.struct_sensitivity = true; + config.context_tracking.last_write_context = true; + return config; + } + + static vsd_configt value_set() + { + vsd_configt config{}; + config.primitive_sensitivity.pointer_sensitivity = true; + config.primitive_sensitivity.array_sensitivity = true; + config.primitive_sensitivity.struct_sensitivity = true; + config.advanced_sensitivities.value_set = true; + return config; + } + + static vsd_configt intervals() + { + vsd_configt config{}; + config.primitive_sensitivity.pointer_sensitivity = true; + config.primitive_sensitivity.array_sensitivity = true; + config.primitive_sensitivity.struct_sensitivity = true; + config.context_tracking.last_write_context = true; + config.advanced_sensitivities.intervals = true; + return config; + } }; class variable_sensitivity_object_factoryt 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 ebdc51b6a48..590f4b4b502 100644 --- a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp @@ -103,12 +103,8 @@ SCENARIO("merge_constant_array_abstract_object", 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( - vsd_configt::from_options(options)); + vsd_configt::constant_domain()); array_utilt util(enviroment, ns); 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 520e19e1d63..db5dfabf80a 100644 --- a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp @@ -134,12 +134,8 @@ SCENARIO("merge_full_struct_abstract_object", 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( - vsd_configt::from_options(options)); + vsd_configt::constant_domain()); struct_utilt util(enviroment, ns); From 366590ed49d26ec1c92824ded3604d29785d47e3 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 12 Mar 2020 17:57:22 +0000 Subject: [PATCH 293/342] Use the config to simplify the code --- .../variable_sensitivity_object_factory.cpp | 32 +++++++++---------- .../variable_sensitivity_object_factory.h | 12 ++----- .../last_written_location.cpp | 3 +- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 3f6be1d8a3a..882e0612a3b 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -36,7 +36,8 @@ variable_sensitivity_object_factoryt::ABSTRACT_OBJECT_TYPET type.id()==ID_c_bool || type.id()==ID_bool || type.id()==ID_integer || type.id()==ID_c_bit_field) { - abstract_object_type=has_interval?INTERVAL:CONSTANT; + abstract_object_type = + configuration.advanced_sensitivities.intervals ? INTERVAL : CONSTANT; } else if(type.id()==ID_floatbv) { @@ -44,23 +45,30 @@ variable_sensitivity_object_factoryt::ABSTRACT_OBJECT_TYPET } else if(type.id()==ID_array) { - abstract_object_type=has_arrays_flag?ARRAY_SENSITIVE:ARRAY_INSENSITIVE; + abstract_object_type = configuration.primitive_sensitivity.array_sensitivity + ? ARRAY_SENSITIVE + : ARRAY_INSENSITIVE; } else if(type.id()==ID_pointer) { - abstract_object_type= - has_pointers_flag?POINTER_SENSITIVE:POINTER_INSENSITIVE; + abstract_object_type = + configuration.primitive_sensitivity.pointer_sensitivity + ? POINTER_SENSITIVE + : POINTER_INSENSITIVE; } else if(type.id()==ID_struct) { - abstract_object_type=has_structs_flag?STRUCT_SENSITIVE:STRUCT_INSENSITIVE; + abstract_object_type = + configuration.primitive_sensitivity.struct_sensitivity + ? STRUCT_SENSITIVE + : STRUCT_INSENSITIVE; } else if(type.id()==ID_union) { abstract_object_type=UNION_INSENSITIVE; } if( - has_value_set_flag && + configuration.advanced_sensitivities.value_set && (abstract_object_type == INTERVAL || abstract_object_type == CONSTANT || abstract_object_type == POINTER_INSENSITIVE || abstract_object_type == POINTER_SENSITIVE)) @@ -119,7 +127,7 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: return initialize_abstract_object( followed_type, top, bottom, e, environment, ns); case ARRAY_SENSITIVE: - return has_interval + return configuration.advanced_sensitivities.intervals ? initialize_abstract_object( followed_type, top, bottom, e, environment, ns) : initialize_abstract_object( @@ -172,14 +180,6 @@ Function: variable_sensitivity_object_factoryt::set_options void variable_sensitivity_object_factoryt::set_options( const vsd_configt &options) { - has_structs_flag = options.primitive_sensitivity.struct_sensitivity; - has_arrays_flag = options.primitive_sensitivity.array_sensitivity; - has_pointers_flag = options.primitive_sensitivity.pointer_sensitivity; - has_last_written_location_context_flag = - options.context_tracking.last_write_context; - has_data_dependencies_context_flag = - options.context_tracking.last_write_context; - has_interval = options.advanced_sensitivities.intervals; - has_value_set_flag = options.advanced_sensitivities.value_set; + this->configuration = options; 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 ee61fb79ca6..a587ab71027 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -164,13 +164,7 @@ class variable_sensitivity_object_factoryt const exprt &e, const abstract_environmentt &enviroment, const namespacet &ns); - bool has_structs_flag; - bool has_arrays_flag; - bool has_pointers_flag; - bool has_last_written_location_context_flag; - bool has_data_dependencies_context_flag; - bool has_value_set_flag; - bool has_interval; + vsd_configt configuration; bool initialized; }; @@ -203,11 +197,11 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: const abstract_environmentt &enviroment, const namespacet &ns) { - if(has_data_dependencies_context_flag) + if(configuration.context_tracking.data_dependency_context) return initialize_context_abstract_object< abstract_object_classt, data_dependency_contextt>( type, top, bottom, e, enviroment, ns); - if(has_last_written_location_context_flag) + if(configuration.context_tracking.last_write_context) return initialize_context_abstract_object< abstract_object_classt, write_location_contextt>( type, top, bottom, e, enviroment, ns); diff --git a/unit/analyses/variable-sensitivity/last_written_location.cpp b/unit/analyses/variable-sensitivity/last_written_location.cpp index 4bec5ae800c..94411159276 100644 --- a/unit/analyses/variable-sensitivity/last_written_location.cpp +++ b/unit/analyses/variable-sensitivity/last_written_location.cpp @@ -52,9 +52,8 @@ SCENARIO("Constructing two environments to make sure we correctly identify modif symbol_table.add(second_sym); namespacet ns(symbol_table); - optionst options; variable_sensitivity_object_factoryt::instance().set_options( - vsd_configt::from_options(options)); + vsd_configt::constant_domain()); WHEN("The identifiers get inserted into two environments") { From 308a4142c40a28ffc3597da418056bdadcefa366 Mon Sep 17 00:00:00 2001 From: Owen Date: Mon, 23 Mar 2020 17:59:10 +0000 Subject: [PATCH 294/342] Make value set entries human-readable Use from_expr instead of constant_expr::get_value() so we don't print hex values --- .../test.desc | 42 ++++++++--------- .../test.desc | 24 +++++----- .../test.desc | 46 +++++++++---------- .../test.desc | 40 ++++++++-------- .../constant_abstract_value.cpp | 12 ++--- 5 files changed, 82 insertions(+), 82 deletions(-) diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc index 3602b0c9757..224dc410240 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc @@ -8,31 +8,31 @@ activate-multi-line-match main#return_value \(\) -> TOP @ \[1\] __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] -__CPROVER_malloc_is_new_array \(\) -> false @ \[7\] +__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[7\] __CPROVER_malloc_object \(\) -> TOP @ \[8\] -__CPROVER_malloc_size \(\) -> 0 @ \[9\] +__CPROVER_malloc_size \(\) -> 0ul @ \[9\] __CPROVER_memory_leak \(\) -> TOP @ \[10\] -__CPROVER_next_thread_id \(\) -> 0 @ \[11\] -__CPROVER_pipe_count \(\) -> 0 @ \[13\] +__CPROVER_next_thread_id \(\) -> 0ul @ \[11\] +__CPROVER_pipe_count \(\) -> 0u @ \[13\] __CPROVER_rounding_mode \(\) -> 0 @ \[14\] -__CPROVER_thread_id \(\) -> 0 @ \[15\] +__CPROVER_thread_id \(\) -> 0ul @ \[15\] __CPROVER_threads_exited \(\) -> TOP @ \[18\] do_arrays::1::bool_ \(\) -> TOP @ \[20\] do_arrays::1::bool_1 \(\) -> TOP @ \[21\] do_arrays::1::bool_2 \(\) -> TOP @ \[22\] -do_arrays::1::x \(\) -> \{\[0\] = A @ \[24\]\n\} @ \[24\] -do_arrays::1::x \(\) -> \{\[0\] = A @ \[24\]\n\[1\] = 14 @ \[25\]\n\} @ \[25\] -do_arrays::1::x \(\) -> \{\[0\] = 1E @ \[26\]\n\[1\] = 14 @ \[25\]\n\} @ \[26\] -do_arrays::1::x \(\) -> \{\[0\] = 1E @ \[26\]\n\[1\] = 28 @ \[27\]\n\} @ \[27\] -do_arrays::1::x \(\) -> \{\[0\] = 1E @ \[26\]\n\[1\] = 1E @ \[28\]\n\} @ \[28\] -do_arrays::1::x \(\) -> \{\[0\] = 1E @ \[29\]\n\[1\] = 1E @ \[28\]\n\} @ \[29\] -do_arrays::1::x \(\) -> \{\[0\] = 5 @ \[30\]\n\[1\] = 1E @ \[28\]\n\} @ \[30\] -do_arrays::1::x \(\) -> \{\[0\] = F @ \[31\]\n\[1\] = 1E @ \[28\]\n\} @ \[31\] -do_arrays::1::x \(\) -> \{\[0\] = F @ \[31\]\n\[1\] = A @ \[32\]\n\} @ \[32\] -do_arrays::1::x \(\) -> \{\[0\] = 14 @ \[34\]\n\[1\] = A @ \[32\]\n\} @ \[34\] -do_arrays::1::x \(\) -> \{\[0\] = 14 @ \[34\, 36\]\n\[1\] = A @ \[32\]\n\} @ \[34\, 36\] -do_arrays::1::x \(\) -> \{\[0\] = 0 @ \[38]\n\[1\] = A @ \[32\]\n\} @ \[38\] -do_arrays::1::x \(\) -> \{\[0\] = 3 @ \[40]\n\[1\] = A @ \[32\]\n\} @ \[40\] -do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[40\, 42]\n\[1\] = A @ \[32\]\n\} @ \[40\, 42\] -do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[40\, 42\, 45]\n\[1\] = A @ \[47\]\n\} @ \[47\] -do_arrays::1::x \(\) -> \{\[0\] = 14 @ \[48]\n\[1\] = A @ \[47\]\n\} @ \[48\] +do_arrays::1::x \(\) -> \{\[0\] = 10 @ \[24\]\n\} @ \[24\] +do_arrays::1::x \(\) -> \{\[0\] = 10 @ \[24\]\n\[1\] = 20 @ \[25\]\n\} @ \[25\] +do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[26\]\n\[1\] = 20 @ \[25\]\n\} @ \[26\] +do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[26\]\n\[1\] = 40 @ \[27\]\n\} @ \[27\] +do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[26\]\n\[1\] = 30 @ \[28\]\n\} @ \[28\] +do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[29\]\n\[1\] = 30 @ \[28\]\n\} @ \[29\] +do_arrays::1::x \(\) -> \{\[0\] = 5 @ \[30\]\n\[1\] = 30 @ \[28\]\n\} @ \[30\] +do_arrays::1::x \(\) -> \{\[0\] = 15 @ \[31\]\n\[1\] = 30 @ \[28\]\n\} @ \[31\] +do_arrays::1::x \(\) -> \{\[0\] = 15 @ \[31\]\n\[1\] = 10 @ \[32\]\n\} @ \[32\] +do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[34\]\n\[1\] = 10 @ \[32\]\n\} @ \[34\] +do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[34\, 36\]\n\[1\] = 10 @ \[32\]\n\} @ \[34\, 36\] +do_arrays::1::x \(\) -> \{\[0\] = 0 @ \[38]\n\[1\] = 10 @ \[32\]\n\} @ \[38\] +do_arrays::1::x \(\) -> \{\[0\] = 3 @ \[40]\n\[1\] = 10 @ \[32\]\n\} @ \[40\] +do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[40\, 42]\n\[1\] = 10 @ \[32\]\n\} @ \[40\, 42\] +do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[40\, 42\, 45]\n\[1\] = 10 @ \[47\]\n\} @ \[47\] +do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[48]\n\[1\] = 10 @ \[47\]\n\} @ \[48\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc index bb4e745e672..c1135495229 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc @@ -8,30 +8,30 @@ activate-multi-line-match main#return_value \(\) -> TOP @ \[1\] __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] -__CPROVER_malloc_is_new_array \(\) -> false @ \[7\] +__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[7\] __CPROVER_malloc_object \(\) -> TOP @ \[8\] -__CPROVER_malloc_size \(\) -> 0 @ \[9\] +__CPROVER_malloc_size \(\) -> 0ul @ \[9\] __CPROVER_memory_leak \(\) -> TOP @ \[10\] -__CPROVER_next_thread_id \(\) -> 0 @ \[11\] -__CPROVER_pipe_count \(\) -> 0 @ \[13\] +__CPROVER_next_thread_id \(\) -> 0ul @ \[11\] +__CPROVER_pipe_count \(\) -> 0u @ \[13\] __CPROVER_rounding_mode \(\) -> 0 @ \[14\] -__CPROVER_thread_id \(\) -> 0 @ \[15\] +__CPROVER_thread_id \(\) -> 0ul @ \[15\] __CPROVER_threads_exited \(\) -> TOP @ \[18\] do_pointers::1::bool_ \(\) -> TOP @ \[20\] do_pointers::1::bool_1 \(\) -> TOP @ \[21\] do_pointers::1::bool_2 \(\) -> TOP @ \[22\] do_pointers::1::x \(\) -> TOP @ \[23\] -do_pointers::1::x \(\) -> A @ \[24\] +do_pointers::1::x \(\) -> 10 @ \[24\] do_pointers::1::x_p \(\) -> TOP @ \[25\] do_pointers::1::y \(\) -> TOP @ \[26\] -do_pointers::1::y \(\) -> 14 @ \[27\] +do_pointers::1::y \(\) -> 20 @ \[27\] do_pointers::1::y_p \(\) -> TOP @ \[28\] do_pointers::1::x_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[29\] -do_pointers::1::x \(\) -> 1E @ \[30\] -do_pointers::1::x \(\) -> 28 @ \[31\] +do_pointers::1::x \(\) -> 30 @ \[30\] +do_pointers::1::x \(\) -> 40 @ \[31\] do_pointers::1::x \(\) -> TOP @ \[32\] -do_pointers::1::x \(\) -> 32 @ \[33\] +do_pointers::1::x \(\) -> 50 @ \[33\] do_pointers::1::y_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[34\] -do_pointers::1::x \(\) -> 3C @ \[35\] +do_pointers::1::x \(\) -> 60 @ \[35\] do_pointers::1::j \(\) -> TOP @ \[36\] -do_pointers::1::j \(\) -> 3C @ \[37\] +do_pointers::1::j \(\) -> 60 @ \[37\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc index 6a8dd629c79..afdd12035d5 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc @@ -8,36 +8,36 @@ activate-multi-line-match main#return_value \(\) -> TOP @ \[1\] __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] -__CPROVER_malloc_is_new_array \(\) -> false @ \[7\] +__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[7\] __CPROVER_malloc_object \(\) -> TOP @ \[8\] -__CPROVER_malloc_size \(\) -> 0 @ \[9\] +__CPROVER_malloc_size \(\) -> 0ul @ \[9\] __CPROVER_memory_leak \(\) -> TOP @ \[10\] -__CPROVER_next_thread_id \(\) -> 0 @ \[11\] -__CPROVER_pipe_count \(\) -> 0 @ \[13\] +__CPROVER_next_thread_id \(\) -> 0ul @ \[11\] +__CPROVER_pipe_count \(\) -> 0u @ \[13\] __CPROVER_rounding_mode \(\) -> 0 @ \[14\] -__CPROVER_thread_id \(\) -> 0 @ \[15\] +__CPROVER_thread_id \(\) -> 0ul @ \[15\] __CPROVER_threads_exited \(\) -> TOP @ \[18\] do_structs::1::bool_ \(\) -> TOP @ \[20\] do_structs::1::bool_1 \(\) -> TOP @ \[21\] do_structs::1::bool_2 \(\) -> TOP @ \[22\] do_structs::1::st \(\) -> \{\} @ \[23\] -do_structs::1::st \(\) -> \{.x=A @ \[24\]\} @ \[24\] -do_structs::1::st \(\) -> \{.x=A @ \[24\]\, .y=14 @ \[25\]\} @ \[25\] -do_structs::1::st \(\) -> \{.x=1E @ \[26\]\, .y=14 @ \[25\]\} @ \[26\] -do_structs::1::st \(\) -> \{.x=1E @ \[26\]\, .y=28 @ \[27\]\} @ \[27\] -do_structs::1::st \(\) -> \{.x=1E @ \[26\]\, .y=1E @ \[28\]\} @ \[28\] -do_structs::1::st \(\) -> \{.x=1E @ \[29\]\, .y=1E @ \[28\]\} @ \[29\] -do_structs::1::st \(\) -> \{.x=5 @ \[30\]\, .y=1E @ \[28\]\} @ \[30\] -do_structs::1::st \(\) -> \{.x=F @ \[31\]\, .y=1E @ \[28\]\} @ \[31\] -do_structs::1::st \(\) -> \{.x=F @ \[31\]\, .y=A @ \[32\]\} @ \[32\] -do_structs::1::st \(\) -> \{.x=14 @ \[34\]\, .y=A @ \[32\]\} @ \[34\] -do_structs::1::st \(\) -> \{.x=14 @ \[34\, 36\]\, .y=A @ \[32\]\} @ \[34\, 36\] -do_structs::1::st \(\) -> \{.x=0 @ \[38\]\, .y=A @ \[32\]\} @ \[38\] -do_structs::1::st \(\) -> \{.x=3 @ \[40\]\, .y=A @ \[32\]\} @ \[40\] -do_structs::1::st \(\) -> \{.x=TOP @ \[40\, 42\]\, .y=A @ \[32\]\} @ \[40\, 42\] -do_structs::1::st \(\) -> \{.x=TOP @ \[40\, 42\, 45\]\, .y=A @ \[32\]\} @ \[40\, 42\, 45\] -do_structs::1::st \(\) -> \{.x=TOP @ \[40\, 42\, 45\]\, .y=A @ \[47\]\} @ \[47\] -do_structs::1::st \(\) -> \{.x=14 @ \[48\]\, .y=A @ \[47\]\} @ \[48\] +do_structs::1::st \(\) -> \{.x=10 @ \[24\]\} @ \[24\] +do_structs::1::st \(\) -> \{.x=10 @ \[24\]\, .y=20 @ \[25\]\} @ \[25\] +do_structs::1::st \(\) -> \{.x=30 @ \[26\]\, .y=20 @ \[25\]\} @ \[26\] +do_structs::1::st \(\) -> \{.x=30 @ \[26\]\, .y=40 @ \[27\]\} @ \[27\] +do_structs::1::st \(\) -> \{.x=30 @ \[26\]\, .y=30 @ \[28\]\} @ \[28\] +do_structs::1::st \(\) -> \{.x=30 @ \[29\]\, .y=30 @ \[28\]\} @ \[29\] +do_structs::1::st \(\) -> \{.x=5 @ \[30\]\, .y=30 @ \[28\]\} @ \[30\] +do_structs::1::st \(\) -> \{.x=15 @ \[31\]\, .y=30 @ \[28\]\} @ \[31\] +do_structs::1::st \(\) -> \{.x=15 @ \[31\]\, .y=10 @ \[32\]\} @ \[32\] +do_structs::1::st \(\) -> \{.x=20 @ \[34\]\, .y=10 @ \[32\]\} @ \[34\] +do_structs::1::st \(\) -> \{.x=20 @ \[34\, 36\]\, .y=10 @ \[32\]\} @ \[34\, 36\] +do_structs::1::st \(\) -> \{.x=0 @ \[38\]\, .y=10 @ \[32\]\} @ \[38\] +do_structs::1::st \(\) -> \{.x=3 @ \[40\]\, .y=10 @ \[32\]\} @ \[40\] +do_structs::1::st \(\) -> \{.x=TOP @ \[40\, 42\]\, .y=10 @ \[32\]\} @ \[40\, 42\] +do_structs::1::st \(\) -> \{.x=TOP @ \[40\, 42\, 45\]\, .y=10 @ \[32\]\} @ \[40\, 42\, 45\] +do_structs::1::st \(\) -> \{.x=TOP @ \[40\, 42\, 45\]\, .y=10 @ \[47\]\} @ \[47\] +do_structs::1::st \(\) -> \{.x=20 @ \[48\]\, .y=10 @ \[47\]\} @ \[48\] do_structs::1::new_age \(\) -> \{\} @ \[49\] -do_structs::1::new_age \(\) -> \{.x=14 @ \[50\]\, .y=A @ \[50\]\} @ \[50\] +do_structs::1::new_age \(\) -> \{.x=20 @ \[50\]\, .y=10 @ \[50\]\} @ \[50\] -- diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc index c8141e00d9c..6ca2373c8d5 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc @@ -7,15 +7,15 @@ main#return_value \(\) -> TOP @ \[1\] __CPROVER_alloca_object \(\) -> TOP @ \[4\] __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] -__CPROVER_malloc_is_new_array \(\) -> false @ \[7\] +__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[7\] __CPROVER_malloc_object \(\) -> TOP @ \[8\] -__CPROVER_malloc_size \(\) -> 0 @ \[9\] +__CPROVER_malloc_size \(\) -> 0ul @ \[9\] __CPROVER_memory_leak \(\) -> TOP @ \[10\] -__CPROVER_next_thread_id \(\) -> 0 @ \[11\] -__CPROVER_next_thread_key \(\) -> 0 @ \[12\] -__CPROVER_pipe_count \(\) -> 0 @ \[13\] +__CPROVER_next_thread_id \(\) -> 0ul @ \[11\] +__CPROVER_next_thread_key \(\) -> 0ul @ \[12\] +__CPROVER_pipe_count \(\) -> 0u @ \[13\] __CPROVER_rounding_mode \(\) -> 0 @ \[14\] -__CPROVER_thread_id \(\) -> 0 @ \[15\] +__CPROVER_thread_id \(\) -> 0ul @ \[15\] __CPROVER_thread_key_dtors \(\) -> TOP @ \[16\] __CPROVER_thread_keys \(\) -> TOP @ \[17\] __CPROVER_threads_exited \(\) -> TOP @ \[18\] @@ -25,25 +25,25 @@ do_variables::1::bool_1 \(\) -> TOP @ \[22\] do_variables::1::bool_2 \(\) -> TOP @ \[23\] global_x \(\) -> 5 @ \[24\] do_variables::1::x \(\) -> TOP @ \[25\] -do_variables::1::x \(\) -> A @ \[26\] +do_variables::1::x \(\) -> 10 @ \[26\] do_variables::1::y \(\) -> TOP @ \[27\] -do_variables::1::y \(\) -> 14 @ \[28\] -do_variables::1::x \(\) -> 1E @ \[29\] -do_variables::1::y \(\) -> 28 @ \[30\] -do_variables::1::y \(\) -> 1E @ \[31\] -do_variables::1::x \(\) -> 1E @ \[32\] +do_variables::1::y \(\) -> 20 @ \[28\] +do_variables::1::x \(\) -> 30 @ \[29\] +do_variables::1::y \(\) -> 40 @ \[30\] +do_variables::1::y \(\) -> 30 @ \[31\] +do_variables::1::x \(\) -> 30 @ \[32\] do_variables::1::x \(\) -> 5 @ \[33\] -do_variables::1::x \(\) -> F @ \[34\] -do_variables::1::y \(\) -> A @ \[35\] -do_variables::1::x \(\) -> 14 @ \[37\] -do_variables::1::x \(\) -> 14 @ \[37\, 39\] -do_variables::1::x \(\) -> 32 @ \[41\] -do_variables::1::x \(\) -> 14 @ \[43\] +do_variables::1::x \(\) -> 15 @ \[34\] +do_variables::1::y \(\) -> 10 @ \[35\] +do_variables::1::x \(\) -> 20 @ \[37\] +do_variables::1::x \(\) -> 20 @ \[37\, 39\] +do_variables::1::x \(\) -> 50 @ \[41\] +do_variables::1::x \(\) -> 20 @ \[43\] do_variables::1::x \(\) -> TOP @ \[43\, 45\] do_variables::1::x \(\) -> 0 @ \[47\] do_variables::1::x \(\) -> 3 @ \[49\] do_variables::1::x \(\) -> TOP @ \[49\, 51\] do_variables::1::x \(\) -> TOP @ \[49\, 51\, 54\] -do_variables::1::y \(\) -> A @ \[56\] -do_variables::1::x \(\) -> 14 @ \[57\] +do_variables::1::y \(\) -> 10 @ \[56\] +do_variables::1::x \(\) -> 20 @ \[57\] -- diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index bdf1556e8b0..e8ed95e40d6 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -9,14 +9,14 @@ #include #include +#include +#include +#include +#include #include -#include #include +#include #include -#include -#include -#include - #include "abstract_enviroment.h" #include "constant_abstract_value.h" @@ -157,7 +157,7 @@ void constant_abstract_valuet::output( { if(!is_top() && !is_bottom()) { - out << to_constant_expr(value).get_value(); + out << from_expr(to_constant_expr(value)); } else { From c6e4237d4500b0973a1d4924180251ac7ae3c4da Mon Sep 17 00:00:00 2001 From: Owen Date: Thu, 26 Mar 2020 14:40:01 +0000 Subject: [PATCH 295/342] Delete write_stack unit test It was written in 2017 but was #if 0-ed out, so it needs to be updated to compile now. ADA-496 has been filed to fix this test up and reintroduce it. --- unit/Makefile | 1 - .../variable-sensitivity/write_stack.cpp | 558 ------------------ 2 files changed, 559 deletions(-) delete mode 100644 unit/analyses/variable-sensitivity/write_stack.cpp diff --git a/unit/Makefile b/unit/Makefile index 3293f97ada7..d5a669574e7 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -20,7 +20,6 @@ SRC += analyses/ai/ai.cpp \ analyses/variable-sensitivity/interval_abstract_value/meet.cpp \ analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp \ analyses/variable-sensitivity/last_written_location.cpp \ - analyses/variable-sensitivity/write_stack.cpp \ ansi-c/max_malloc_size.cpp \ ansi-c/type2name.cpp \ big-int/big-int.cpp \ diff --git a/unit/analyses/variable-sensitivity/write_stack.cpp b/unit/analyses/variable-sensitivity/write_stack.cpp deleted file mode 100644 index f300e280021..00000000000 --- a/unit/analyses/variable-sensitivity/write_stack.cpp +++ /dev/null @@ -1,558 +0,0 @@ -/*******************************************************************\ - - Module: Write Stack Unit Tests - - Author: DiffBlue Limited. All rights reserved. - -\*******************************************************************/ - -/// \file -/// Unit tests for construction of write stack - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if 0 -#include -#include - - -SCENARIO("Constructing write stacks", - "[core][analyses][variable-sensitivity][continuation-stack]") -{ - 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); - - config.set_arch("none"); - - abstract_environmentt environment; - environment.make_top(); - - c_to_exprt to_expr; - - GIVEN("A int x") - { - typet basic_symbol_type=signedbv_typet(32); - symbol_table.add( - auxiliary_symbolt("x", basic_symbol_type)); - - WHEN("Constructing from &x") - { - exprt in_expr=to_expr("&x", ns); - CAPTURE(expr2c(in_expr, ns)); - - THEN("The constructed stack should be &x") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const exprt &object=out_expr.op0(); - require_exprt::require_symbol(object, "x"); - } - } - } - GIVEN("A int a[5]") - { - typet array_type= - array_typet(signedbv_typet(32), constant_exprt::integer_constant(5)); - symbol_table.add(auxiliary_symbolt("a", array_type)); - - WHEN("Constructing from a") - { - exprt in_expr=to_expr("a", ns); - THEN("The constructed stack should be &a[0]") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const index_exprt &index_expr= - require_exprt::require_index(out_expr.op0(), 0); - require_exprt::require_symbol(index_expr.array(), "a"); - } - } - WHEN("Constructing from &a") - { - exprt in_expr=to_expr("&a", ns); - - THEN("The constructed stack should be &a") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - // TODO: make consistent with above - REQUIRE(out_expr.id()==ID_address_of); - require_exprt::require_symbol(out_expr.op0(), "a"); - } - } - WHEN("Constructing from &a[0]") - { - exprt in_expr=to_expr("&a[0]", ns); - - CAPTURE(expr2c(in_expr, ns)); - THEN("The constructed stack should be &a[0]") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const exprt &object=out_expr.op0(); - const index_exprt &index_expr= - require_exprt::require_index(object, 0); - require_exprt::require_symbol(index_expr.array(), "a"); - } - } - WHEN("Constructing from &a[1]") - { - exprt in_expr=to_expr("&a[1]", ns); - - CAPTURE(expr2c(in_expr, ns)); - THEN("The constructed stack should be &a[1]") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const index_exprt &index_expr= - require_exprt::require_index(out_expr.op0(), 1); - require_exprt::require_symbol(index_expr.array(), "a"); - } - } - WHEN("Constructing from &a[0]+1") - { - exprt in_expr=to_expr("&a[0]+1", ns); - - CAPTURE(expr2c(in_expr, ns)); - THEN("The constructed stack should be &a[1]") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const index_exprt &index_expr= - require_exprt::require_index(out_expr.op0(), 1); - require_exprt::require_symbol(index_expr.array(), "a"); - } - } - WHEN("Constructing from &a[1]+1") - { - exprt in_expr=to_expr("&a[1]+1", ns); - - CAPTURE(expr2c(in_expr, ns)); - - THEN("The constructed stack should be &a[2]") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const index_exprt &index_expr= - require_exprt::require_index(out_expr.op0(), 2); - require_exprt::require_symbol(index_expr.array(), "a"); - } - } - WHEN("Constructing from &a[1]-1") - { - exprt in_expr=to_expr("&a[1]-1", ns); - - CAPTURE(expr2c(in_expr, ns)); - - THEN("The constructed stack should be &a[0]") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const index_exprt &index_expr= - require_exprt::require_index(out_expr.op0(), 0); - require_exprt::require_symbol(index_expr.array(), "a"); - } - } - WHEN("Constructing from 1+&a[1]") - { - exprt in_expr=to_expr("1+&a[1]", ns); - - CAPTURE(expr2c(in_expr, ns)); - - THEN("The constructed stack should be &a[2]") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const index_exprt &index_expr= - require_exprt::require_index(out_expr.op0(), 2); - require_exprt::require_symbol(index_expr.array(), "a"); - } - } - GIVEN("A symbol int x") - { - typet basic_symbol_type=signedbv_typet(32); - symbolt basic_symbol= - auxiliary_symbolt("x", basic_symbol_type); - symbol_table.add(basic_symbol); - - WHEN("Constructing from &a[x] (x top)") - { - exprt in_expr=to_expr("&a[x]", ns); - - CAPTURE(expr2c(in_expr, ns)); - THEN("The constructed stack should be &a[TOP]") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const index_exprt &index_expr= - require_exprt::require_top_index(out_expr.op0()); - require_exprt::require_symbol(index_expr.array(), "a"); - } - } - WHEN("Constructing from &a[x] (x known to be 2") - { - // Create an abstract_object_pointer representing 2 - abstract_object_pointert x_value= - environment.abstract_object_factory( - basic_symbol_type, - to_expr("2", ns), - ns); - environment.assign(basic_symbol.symbol_expr(), x_value, ns); - - exprt in_expr=to_expr("&a[x]", ns); - - CAPTURE(expr2c(in_expr, ns)); - THEN("The constructed stack should be &a[2]") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const index_exprt &index_expr= - require_exprt::require_index(out_expr.op0(), 2); - require_exprt::require_symbol(index_expr.array(), "a"); - } - } - } - } - - GIVEN("A struct str{ int comp, int comp2 }") - { - struct_union_typet::componentt component("comp", signedbv_typet(32)); - struct_union_typet::componentt component2("comp2", signedbv_typet(32)); - struct_typet struct_type; - struct_type.set_tag("str"); - struct_type.components().push_back(component); - struct_type.components().push_back(component2); - - symbolt struct_symbol; - struct_symbol.base_name="str"; - struct_symbol.name="tag-str"; - struct_symbol.type=struct_type; - struct_symbol.is_type=true; - - symbol_table.add(struct_symbol); - - GIVEN("A struct str s") - { - symbol_table.add( - auxiliary_symbolt("s", struct_type)); - - WHEN("Constructing from &s.comp") - { - exprt in_expr=to_expr("&s.comp", ns); - CAPTURE(expr2c(in_expr, ns)); - - THEN("The constructed stack should be &s.comp") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const member_exprt &member_exrp= - require_exprt::require_member(out_expr.op0(), "comp"); - // TODO: verify member expr - require_exprt::require_symbol(member_exrp.compound(), "s"); - } - } - WHEN("Constructing from &s.comp2") - { - exprt in_expr=to_expr("&s.comp2", ns); - CAPTURE(expr2c(in_expr, ns)); - - THEN("The constructed stack should be &s.comp2") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const member_exprt &member_exrp= - require_exprt::require_member(out_expr.op0(), "comp2"); - // TODO: verify member expr - require_exprt::require_symbol(member_exrp.compound(), "s"); - } - } - WHEN("Constructing from &s") - { - exprt in_expr=to_expr("&s", ns); - CAPTURE(expr2c(in_expr, ns)); - - THEN("Then should get a write stack representing &s") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const exprt &object=out_expr.op0(); - require_exprt::require_symbol(object, "s"); - } - } - WHEN("Constructing from (int *)&s") - { - // TODO: we could in theory analyse the struct and offset the pointer - // but not yet - exprt in_expr=to_expr("(int *)&s", ns); - CAPTURE(expr2c(in_expr, ns)); - - THEN("Then should get a top stack") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE(stack.is_top_value()); - } - } - WHEN("Constructing from &s.comp + 1") - { - // TODO: we could in theory analyse the struct and offset the pointer - // but not yet - exprt in_expr=to_expr("&s.comp + 1", ns); - CAPTURE(expr2c(in_expr, ns)); - - THEN("Then should get a top stack") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE(stack.is_top_value()); - } - } - } - GIVEN("struct str arr_s[5]") - { - typet array_type= - array_typet(struct_type, constant_exprt::integer_constant(5)); - symbol_table.add( - auxiliary_symbolt("arr_s", array_type)); - - WHEN("&arr_s[1].comp") - { - exprt in_expr=to_expr("&arr_s[1].comp", ns); - CAPTURE(expr2c(in_expr, ns)); - - THEN("The constructed stack should be &arr_s[1].comp") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - - const member_exprt &member_expr= - require_exprt::require_member(out_expr.op0(), "comp"); - const index_exprt &index_expr= - require_exprt::require_index(member_expr.compound(), 1); - - require_exprt::require_symbol(index_expr.array(), "arr_s"); - } - } - WHEN("&arr_s[1]") - { - exprt in_expr=to_expr("&arr_s[1]", ns); - CAPTURE(expr2c(in_expr, ns)); - - THEN("The constructed stack should be TOP") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const exprt &object=out_expr.op0(); - const index_exprt &index_expr=require_exprt::require_index(object, 1); - require_exprt::require_symbol(index_expr.array(), "arr_s"); - } - } - GIVEN("A symbol int x") - { - typet basic_symbol_type=signedbv_typet(32); - symbol_table.add( - auxiliary_symbolt("x", basic_symbol_type)); - - WHEN("Constructing from &arr_s[x].comp (x top)") - { - exprt in_expr=to_expr("&arr_s[x].comp", ns); - - CAPTURE(expr2c(in_expr, ns)); - THEN("The constructed stack should be &arr_s[TOP].comp") - { - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE_FALSE(stack.is_top_value()); - const exprt &out_expr=stack.to_expression(); - - CAPTURE(expr2c(out_expr, ns)); - - REQUIRE(out_expr.id()==ID_address_of); - const member_exprt &member_expr= - require_exprt::require_member(out_expr.op0(), "comp"); - - const index_exprt &index_expr= - require_exprt::require_top_index(member_expr.compound()); - - require_exprt::require_symbol(index_expr.array(), "arr_s"); - } - } - } - } - } - GIVEN("A pointer to an integer int * p = &x") - { - // in a top environment - to construct from say (p + 1) we should always - // return top. If the enviroment was not top, we could do better if p has an - // offset at the top of its write_stack. Of course if it doesn't - - // int x; - typet basic_symbol_type=signedbv_typet(32); - symbol_table.add( - auxiliary_symbolt("x", basic_symbol_type)); - - // int * p - typet pointer_type=pointer_typet(basic_symbol_type); - symbolt pointer_symbol= - auxiliary_symbolt("p", pointer_type); - symbol_table.add(pointer_symbol); - - // Create an abstract_object_pointer representing 2 - abstract_object_pointert x_value= - environment.abstract_object_factory( - pointer_type, - to_expr("&x", ns), - ns); - environment.assign(pointer_symbol.symbol_expr(), x_value, ns); - - WHEN("Constructing the write stack from p + 1") - { - exprt in_expr=to_expr("p + 1", ns); - CAPTURE(expr2c(in_expr, ns)); - - THEN("The constructed stack should be TOP") - { - // Since we don't allow constructing a pointer to a struct yet - auto stack=write_stackt(in_expr, environment, ns); - REQUIRE(stack.is_top_value()); - } - } - WHEN("Constructing the write stack from 1 + p") - { - exprt in_expr=to_expr("1 + p", ns); - CAPTURE(expr2c(in_expr, ns)); - - auto stack=write_stackt(in_expr, environment, ns); - - THEN("Get a top write stack") - { - REQUIRE(stack.is_top_value()); - } - } - WHEN("Constructing the write stack from p - 1") - { - exprt in_expr=to_expr("p - 1", ns); - CAPTURE(expr2c(in_expr, ns)); - - auto stack=write_stackt(in_expr, environment, ns); - - THEN("Get a top write stack") - { - REQUIRE(stack.is_top_value()); - } - } - WHEN("Constructing the write stack from &p[1]") - { - exprt in_expr=to_expr("&p[1]", ns); - CAPTURE(expr2c(in_expr, ns)); - - auto stack=write_stackt(in_expr, environment, ns); - - THEN("Get a top write stack") - { - REQUIRE(stack.is_top_value()); - } - } - } -} -#endif - From e24c17a7c6348c0b0625ddfd22aaf4c2e2ba5fed Mon Sep 17 00:00:00 2001 From: Owen Date: Tue, 24 Mar 2020 11:52:48 +0000 Subject: [PATCH 296/342] Various miscellaneous fixes Most of these are needed to make clang-format happy, or the linter, or to make it compile on Windows --- .../test.desc | 1 - .../test.desc | 1 - .../test.desc | 34 +++++++++---------- .../test.desc | 34 +++++++++---------- .../test.desc | 2 +- .../test.desc | 2 +- .../abstract_enviroment.cpp | 2 +- .../variable-sensitivity/abstract_object.cpp | 21 ++++-------- .../variable-sensitivity/abstract_object.h | 9 +++-- .../context_abstract_object.cpp | 1 + .../data_dependency_context.cpp | 1 - .../variable_sensitivity_dependence_graph.cpp | 13 ++++--- .../variable_sensitivity_domain.cpp | 6 ++-- .../write_location_context.cpp | 4 ++- .../write_stack_entry.cpp | 12 ++++++- 15 files changed, 75 insertions(+), 68 deletions(-) diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc index ff7983d6d35..ffbac31223a 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc @@ -7,5 +7,4 @@ main.c ^\[simple_test\.assertion\.2\] line 26 global==0: SUCCESS$ ^\[simple_test\.assertion\.3\] line 31 i==1: SUCCESS$ ^\[simple_test\.assertion\.4\] line 32 global==2: SUCCESS$ - -- diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-02/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-02/test.desc index 4971c164466..1f0332d5afc 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph-02/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-02/test.desc @@ -6,6 +6,5 @@ activate-multi-line-match ^SIGNAL=0$ Control dependencies: [0-9]+ \[TRUE\]\n.*\n.*\n\s+a = 1; Control dependencies: [0-9]+ \[UNCONDITIONAL\]\n.*\n.*\n\s+a = 2; - -- ^warning: ignoring diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc index d3fbd5ad478..7af73c46f2c 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc @@ -8,30 +8,30 @@ Data dependencies: 58 \[st.b\] Data dependencies: 1 \[st.a\], 58 \[st.a\] Data dependencies: 4 \[st.b\], 58 \[st.b\] Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\] -Data dependencies: 52 \[ar\[\(signed long int\)0\]\] -Data dependencies: 52 \[ar\[\(signed long int\)1\]\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\] -Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\] -Data dependencies: 19 \[arr\[\(signed long int\)1\]\] -Data dependencies: 18 \[arr\[\(signed long int\)0\]\] -Data dependencies: 19 \[arr\[\(signed long int\)1\]\] -Data dependencies: 20 \[arr\[\(signed long int\)2\]\], 22 \[arr\[\(signed long int\)2\]\] +Data dependencies: 52 \[ar\[\([^)]*\)0\]\] +Data dependencies: 52 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\] +Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\] +Data dependencies: 19 \[arr\[\([^)]*\)1\]\] +Data dependencies: 18 \[arr\[\([^)]*\)0\]\] +Data dependencies: 19 \[arr\[\([^)]*\)1\]\] +Data dependencies: 20 \[arr\[\([^)]*\)2\]\], 22 \[arr\[\([^)]*\)2\]\] Data dependencies: 1 \[st.a\], 58 \[st.a\], 62 \[st.a\] Data dependencies: 4 \[st.b\], 58 \[st.b\], 65 \[st.b\] Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\], 62 \[st.a\], 65 \[st.b\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\], 73 \[ar\[\(signed long int\)0\]\] -Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\], 76 \[ar\[\(signed long int\)1\]\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 73 \[ar\[\(signed long int\)0\]\], 76 \[ar\[\(signed long int\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\], 73 \[ar\[\([^)]*\)0\]\] +Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\], 76 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 73 \[ar\[\([^)]*\)0\]\], 76 \[ar\[\([^)]*\)1\]\] Data dependencies: 1 \[st.a\], 58 \[st.a\] Data dependencies: 4 \[st.b\], 58 \[st.b\] Data dependencies: 1 \[st.a\], 58 \[st.a\], 62 \[st.a\] Data dependencies: 4 \[st.b\], 58 \[st.b\], 65 \[st.b\] Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\], 62 \[st.a\], 65 \[st.b\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\] -Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\], 73 \[ar\[\(signed long int\)0\]\] -Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\], 76 \[ar\[\(signed long int\)1\]\] -Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 73 \[ar\[\(signed long int\)0\]\], 76 \[ar\[\(signed long int\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\] +Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\], 73 \[ar\[\([^)]*\)0\]\] +Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\], 76 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 73 \[ar\[\([^)]*\)0\]\], 76 \[ar\[\([^)]*\)1\]\] -- ^warning: ignoring diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc index ce8b4f92a48..60d786367b3 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc @@ -8,31 +8,31 @@ file1.c file2.c --dependence-graph-vs --structs --arrays --show ^Data dependencies: 1 \[st.a\], 58 \[st.a\]$ ^Data dependencies: 4 \[st.b\], 58 \[st.b\]$ ^Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\]$ -^Data dependencies: 52 \[ar\[\(signed long int\)0\]\]$ +^Data dependencies: 52 \[ar\[\([^)]*\)0\]\]$ ^Data dependencies: 6 \[out1\]$ -^Data dependencies: 52 \[ar\[\(signed long int\)1\]\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\]$ -^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\]$ -^Data dependencies: 19 \[arr\[\(signed long int\)1\]\]$ -^Data dependencies: 18 \[arr\[\(signed long int\)0\]\]$ -^Data dependencies: 19 \[arr\[\(signed long int\)1\]\]$ -^Data dependencies: 20 \[arr\[\(signed long int\)2\]\], 22 \[arr\[\(signed long int\)2\]\]$ +^Data dependencies: 52 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\]$ +^Data dependencies: 19 \[arr\[\([^)]*\)1\]\]$ +^Data dependencies: 18 \[arr\[\([^)]*\)0\]\]$ +^Data dependencies: 19 \[arr\[\([^)]*\)1\]\]$ +^Data dependencies: 20 \[arr\[\([^)]*\)2\]\], 22 \[arr\[\([^)]*\)2\]\]$ ^Data dependencies: 1 \[st.a\], 58 \[st.a\], 62 \[st.a\]$ ^Data dependencies: 4 \[st.b\], 58 \[st.b\], 65 \[st.b\]$ ^Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\], 62 \[st.a\], 65 \[st.b\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\], 73 \[ar\[\(signed long int\)0\]\]$ -^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\], 76 \[ar\[\(signed long int\)1\]\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 73 \[ar\[\(signed long int\)0\]\], 76 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\], 73 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\], 76 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 73 \[ar\[\([^)]*\)0\]\], 76 \[ar\[\([^)]*\)1\]\]$ ^Data dependencies: 1 \[st.a\], 58 \[st.a\]$ ^Data dependencies: 4 \[st.b\], 58 \[st.b\]$ ^Data dependencies: 1 \[st.a\], 58 \[st.a\], 62 \[st.a\]$ ^Data dependencies: 4 \[st.b\], 58 \[st.b\], 65 \[st.b\]$ ^Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\], 62 \[st.a\], 65 \[st.b\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\]$ -^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 52 \[ar\[\(signed long int\)0\]\], 73 \[ar\[\(signed long int\)0\]\]$ -^Data dependencies: 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)1\]\], 76 \[ar\[\(signed long int\)1\]\]$ -^Data dependencies: 10 \[ar\[\(signed long int\)0\]\], 13 \[ar\[\(signed long int\)1\]\], 52 \[ar\[\(signed long int\)0\], ar\[\(signed long int\)1\]\], 73 \[ar\[\(signed long int\)0\]\], 76 \[ar\[\(signed long int\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\], 73 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\], 76 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 73 \[ar\[\([^)]*\)0\]\], 76 \[ar\[\([^)]*\)1\]\]$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph16/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph16/test.desc index 0d729bc4a85..d9c98288288 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph16/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph16/test.desc @@ -6,5 +6,5 @@ activate-multi-line-match ^SIGNAL=0$ // Assignment from the result of a function call to a function with no body // should have a data dependency on the function -^Data dependencies: 3 \[f2\]\n(.*\n).*\/\/ 4 file .*main.c line 15 function main\n.*t2 = NONDET\(signed int\); +^Data dependencies: 3 \[f2\]\n(.*\n).*\/\/ 4 file .*main.c line 15 function main\n.*t2 = NONDET\([^)]*\); -- diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc index 3df8ae018d1..cc082a54cac 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc @@ -4,5 +4,5 @@ main.c activate-multi-line-match ^EXIT=0$ ^SIGNAL=0$ -\*\*\*\* 9 file .*main\.c line 22 function main\nControl dependencies: 34 \[UNCONDITIONAL\]\nData dependencies: 1 \[g_a\[\(signed long int\)i\]\], 2 \[g_a\[\(signed long int\)i\]\], 3 \[g_a\[\(signed long int\)i\]\], 7 \[g_a\[\(signed long int\)i\]\] +\*\*\*\* 9 file .*main\.c line 22 function main\nControl dependencies: 34 \[UNCONDITIONAL\]\nData dependencies: 1 \[g_a\[\([^)]*\)i\]\], 2 \[g_a\[\([^)]*\)i\]\], 3 \[g_a\[\([^)]*\)i\]\], 7 \[g_a\[\([^)]*\)i\]\] -- diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index c4e8fc99887..43aa2d2bf36 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -265,7 +265,7 @@ Function: abstract_object_pointert abstract_environmentt::write 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 + merge_write - Are we 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. diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index b40374191f1..f0638dbf738 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -61,21 +61,11 @@ abstract_objectt::abstract_objectt(const typet &type, bool top, bool bottom): PRECONDITION(!(top && bottom)); } -/*******************************************************************\ - -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: Construct an abstract object from the expression - -\*******************************************************************/ - +/// Construct an abstract object from the expression +/// \param expr: The expression to use as the starting pointer for an abstract +/// object +/// \param environment: The environment this abstract object is being created in +/// \param ns: The namespace abstract_objectt::abstract_objectt( const exprt &expr, const abstract_environmentt &environment, @@ -527,6 +517,7 @@ void abstract_objectt::dump_map( /** * \brief Dump all elements in m1 that are different or missing in m2 * + * \param out the stream to write output to * \param m1 the 'target' sharing_map * \param m2 the reference sharing map */ diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 7b0ed4188f0..c4ab9b28f0a 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -24,13 +24,12 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_H - - +#include +#include +#include +#include #include #include -#include -#include -#include #include #include diff --git a/src/analyses/variable-sensitivity/context_abstract_object.cpp b/src/analyses/variable-sensitivity/context_abstract_object.cpp index b89bae9842b..a3e5a5fece1 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/context_abstract_object.cpp @@ -102,6 +102,7 @@ abstract_object_pointert context_abstract_objectt::write( * * \param expr the expression to evaluate and find the result of. This will * be the symbol referred to be op0() + * \param operands: the operands to use instead of expr.operands() * \param environment the abstract environment in which to resolve 'expr' * \param ns the current namespace * diff --git a/src/analyses/variable-sensitivity/data_dependency_context.cpp b/src/analyses/variable-sensitivity/data_dependency_context.cpp index 234cdc2e8d3..06dd3a50d31 100644 --- a/src/analyses/variable-sensitivity/data_dependency_context.cpp +++ b/src/analyses/variable-sensitivity/data_dependency_context.cpp @@ -12,7 +12,6 @@ Author: Diffblue Ltd */ #include -#include #include "data_dependency_context.h" diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index e5e409a24c8..62a2fcf284c 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -54,7 +54,10 @@ void variable_sensitivity_dependence_domaint::eval_data_deps( * the data dependencies, this involves calculating all the data * dependencies that exist in the 'to' instruction. * + * \param function_from the function of the instruction before the abstract + * domain * \param from the instruction before the abstract domain + * \param function_to the function of the instruction after the abstract domain * \param to the instruction after the abstract domain * \param ai the abstract interpreter * \param ns the namespace @@ -432,8 +435,10 @@ bool variable_sensitivity_dependence_domaint::merge( * * \param function_call: The local of the merge - values from here will be * taken if they have not been modified - * \param function_start: THe base of the merge - changes that have been made - * between here and this will be retained. + * \param function_start: The base of the merge - changes that have been made + * between here and the end will be retained. + * \param function_end: The end of the merge - changes that have been made +/// between the start and here will be retained. * \param ns: The global namespace */ void variable_sensitivity_dependence_domaint::merge_three_way_function_return( @@ -445,8 +450,8 @@ void variable_sensitivity_dependence_domaint::merge_three_way_function_return( // The gathering of the data dependencies for the domain is handled by the // 'transform' and simply relies on the underlying domains with their // data_dependency_context to be correct. Therefore all we need to ensure at - // the three way merge is that the underlying variable senstivitiy domain - // does it's three way merge. + // the three way merge is that the underlying variable sensitivity domain + // does its three way merge. variable_sensitivity_domaint::merge_three_way_function_return( function_call, function_start, diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index cab6594900c..e102c191460 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -550,8 +550,10 @@ bool variable_sensitivity_domaint::ignore_function_call_transform( /// modified will be taken from the \p function_call domain. /// \param function_call: The local of the merge - values from here will be /// taken if they have not been modified -/// \param function_start: THe base of the merge - changes that have been made -/// between here and this will be retained. +/// \param function_start: The base of the merge - changes that have been made +/// between here and the end will be retained. +/// \param function_end: The end of the merge - changes that have been made +/// between the start and here will be retained. /// \param ns: The global namespace void variable_sensitivity_domaint::merge_three_way_function_return( const ai_domain_baset &function_call, diff --git a/src/analyses/variable-sensitivity/write_location_context.cpp b/src/analyses/variable-sensitivity/write_location_context.cpp index 14494a35732..e135c84b133 100644 --- a/src/analyses/variable-sensitivity/write_location_context.cpp +++ b/src/analyses/variable-sensitivity/write_location_context.cpp @@ -6,9 +6,11 @@ \*******************************************************************/ -#include #include + #include +#include + #include "write_location_context.h" /** diff --git a/src/analyses/variable-sensitivity/write_stack_entry.cpp b/src/analyses/variable-sensitivity/write_stack_entry.cpp index 9f0f0407bf6..8e65def0c3d 100644 --- a/src/analyses/variable-sensitivity/write_stack_entry.cpp +++ b/src/analyses/variable-sensitivity/write_stack_entry.cpp @@ -1,5 +1,15 @@ -#include +/*******************************************************************\ + + Module: Analyses Variable Sensitivity + + Author: DiffBlue Limited. All rights reserved. +\*******************************************************************/ + +/// \file +/// Represents an entry in the write_stackt + +#include #include From 882addff141d54e454c0dcce64ba417fffd0fb54 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 12 Mar 2020 18:21:42 +0000 Subject: [PATCH 297/342] Add tests for value-set domain --- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../value-set-function-pointers-arrays/main.c | 41 ++++++++ .../test.desc | 13 +++ .../main.c | 30 ++++++ .../test.desc | 10 ++ .../value-set-function-pointers-simple/main.c | 53 ++++++++++ .../test.desc | 28 ++++++ .../main.c | 55 +++++++++++ .../test.desc | 16 +++ .../goto-analyzer/value-set-simple/main.c | 50 ++++++++++ .../value-set-simple/test_show.desc | 10 ++ .../value-set-simple/test_verify.desc | 22 +++++ .../goto-analyzer/value-set-structs/main.c | 67 +++++++++++++ .../value-set-structs/test_show.desc | 10 ++ .../value-set-structs/test_verify.desc | 26 +++++ unit/analyses/variable-sensitivity/eval.cpp | 97 +++++++++++++++++++ 19 files changed, 532 insertions(+), 4 deletions(-) create mode 100644 regression/goto-analyzer/value-set-function-pointers-arrays/main.c create mode 100644 regression/goto-analyzer/value-set-function-pointers-arrays/test.desc create mode 100644 regression/goto-analyzer/value-set-function-pointers-incremented/main.c create mode 100644 regression/goto-analyzer/value-set-function-pointers-incremented/test.desc create mode 100644 regression/goto-analyzer/value-set-function-pointers-simple/main.c create mode 100644 regression/goto-analyzer/value-set-function-pointers-simple/test.desc create mode 100644 regression/goto-analyzer/value-set-function-pointers-structs/main.c create mode 100644 regression/goto-analyzer/value-set-function-pointers-structs/test.desc create mode 100644 regression/goto-analyzer/value-set-simple/main.c create mode 100644 regression/goto-analyzer/value-set-simple/test_show.desc create mode 100644 regression/goto-analyzer/value-set-simple/test_verify.desc create mode 100644 regression/goto-analyzer/value-set-structs/main.c create mode 100644 regression/goto-analyzer/value-set-structs/test_show.desc create mode 100644 regression/goto-analyzer/value-set-structs/test_verify.desc create mode 100644 unit/analyses/variable-sensitivity/eval.cpp diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc index 224dc410240..69735a3a3b2 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc @@ -10,7 +10,7 @@ __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] __CPROVER_malloc_is_new_array \(\) -> FALSE @ \[7\] __CPROVER_malloc_object \(\) -> TOP @ \[8\] -__CPROVER_malloc_size \(\) -> 0ul @ \[9\] +__CPROVER_malloc_size \(\) -> 0ull? @ \[9\] __CPROVER_memory_leak \(\) -> TOP @ \[10\] __CPROVER_next_thread_id \(\) -> 0ul @ \[11\] __CPROVER_pipe_count \(\) -> 0u @ \[13\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc index c1135495229..6656d3cbccc 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc @@ -10,7 +10,7 @@ __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] __CPROVER_malloc_is_new_array \(\) -> FALSE @ \[7\] __CPROVER_malloc_object \(\) -> TOP @ \[8\] -__CPROVER_malloc_size \(\) -> 0ul @ \[9\] +__CPROVER_malloc_size \(\) -> 0ull? @ \[9\] __CPROVER_memory_leak \(\) -> TOP @ \[10\] __CPROVER_next_thread_id \(\) -> 0ul @ \[11\] __CPROVER_pipe_count \(\) -> 0u @ \[13\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc index afdd12035d5..7be8d8a35ca 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc @@ -10,7 +10,7 @@ __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] __CPROVER_malloc_is_new_array \(\) -> FALSE @ \[7\] __CPROVER_malloc_object \(\) -> TOP @ \[8\] -__CPROVER_malloc_size \(\) -> 0ul @ \[9\] +__CPROVER_malloc_size \(\) -> 0ull? @ \[9\] __CPROVER_memory_leak \(\) -> TOP @ \[10\] __CPROVER_next_thread_id \(\) -> 0ul @ \[11\] __CPROVER_pipe_count \(\) -> 0u @ \[13\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc index 6ca2373c8d5..cb85440f564 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc @@ -9,7 +9,7 @@ __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] __CPROVER_malloc_is_new_array \(\) -> FALSE @ \[7\] __CPROVER_malloc_object \(\) -> TOP @ \[8\] -__CPROVER_malloc_size \(\) -> 0ul @ \[9\] +__CPROVER_malloc_size \(\) -> 0ull? @ \[9\] __CPROVER_memory_leak \(\) -> TOP @ \[10\] __CPROVER_next_thread_id \(\) -> 0ul @ \[11\] __CPROVER_next_thread_key \(\) -> 0ul @ \[12\] diff --git a/regression/goto-analyzer/value-set-function-pointers-arrays/main.c b/regression/goto-analyzer/value-set-function-pointers-arrays/main.c new file mode 100644 index 00000000000..22d42a5f48d --- /dev/null +++ b/regression/goto-analyzer/value-set-function-pointers-arrays/main.c @@ -0,0 +1,41 @@ +#include + +typedef int (*fptr_t)(int); + +int f(int x) +{ + return x + 1; +} +int g(int x) +{ + return x; +} +int h(int x) +{ + return x - 1; +} + +int main(void) +{ + int nondet_choice; + + // Reading from array + fptr_t fun1; + fptr_t fun_array1[] = {f, g}; + if(nondet_choice) + fun1 = fun_array1[0]; + else + fun1 = fun_array1[1]; + fun1(5); + + // Writing to array + fptr_t fun_array2[2]; + if(nondet_choice) + fun_array2[0] = f; + else + fun_array2[0] = g; + fptr_t fun_array3[2]; + fun_array3[0] = fun_array2[0]; + fun_array3[1] = fun_array2[1]; + fun_array3[0](5); +} diff --git a/regression/goto-analyzer/value-set-function-pointers-arrays/test.desc b/regression/goto-analyzer/value-set-function-pointers-arrays/test.desc new file mode 100644 index 00000000000..4caa368fd04 --- /dev/null +++ b/regression/goto-analyzer/value-set-function-pointers-arrays/test.desc @@ -0,0 +1,13 @@ +CORE +main.c +--variable --structs --arrays --pointers --value-set --show --pointer-check +^file main.c line 29 function main: replacing function pointer by 2 possible targets$ +^file main.c line 40 function main: replacing function pointer by 2 possible targets$ +^main::1::fun1 \(\) -> value-set-begin: ptr ->\([fg]\), ptr ->\([fg]\), :value-set-end$ +^main::1::fun_array3 \(\) -> \{\[0\] = value-set-begin: ptr ->\([fg]\), ptr ->\([fg]\), :value-set-end$ +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring +^main::1::fun1 \(\) -> value-set-begin: .*ptr ->\(h\).* :value-set-end$ +^main::1::fun_array3 \(\) -> \{\[0\] = value-set-begin: .*ptr ->\(h\).* :value-set-end$ diff --git a/regression/goto-analyzer/value-set-function-pointers-incremented/main.c b/regression/goto-analyzer/value-set-function-pointers-incremented/main.c new file mode 100644 index 00000000000..6c47bc5e1c4 --- /dev/null +++ b/regression/goto-analyzer/value-set-function-pointers-incremented/main.c @@ -0,0 +1,30 @@ +#include + +typedef int (*fptr_t)(int); +fptr_t fun_global, fun_global_show; + +int f(int x) +{ + return x + 1; +} +int g(int x) +{ + return x; +} +int h(int x) +{ + return x - 1; +} + +int main(void) +{ + // This line is needed so that g is considered as a possibility for the TOP + // value + fptr_t dummy = g; + + // function pointer incremented should be top + fptr_t fun_incremented = f; + ++fun_incremented; + fun_incremented(5); + fptr_t fun_incremented_show = fun_incremented; +} diff --git a/regression/goto-analyzer/value-set-function-pointers-incremented/test.desc b/regression/goto-analyzer/value-set-function-pointers-incremented/test.desc new file mode 100644 index 00000000000..a675596f194 --- /dev/null +++ b/regression/goto-analyzer/value-set-function-pointers-incremented/test.desc @@ -0,0 +1,10 @@ +CORE +main.c +--variable --structs --arrays --pointers --value-set --show --pointer-check +^file main.c line 28 function main: replacing function pointer by 2 possible targets$ +^main::1::fun_incremented_show \(\) -> TOP$ +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring +^main::1::fun_incremented_show \(\) -> value-set-begin: .* :value-set-end$ diff --git a/regression/goto-analyzer/value-set-function-pointers-simple/main.c b/regression/goto-analyzer/value-set-function-pointers-simple/main.c new file mode 100644 index 00000000000..11debd48721 --- /dev/null +++ b/regression/goto-analyzer/value-set-function-pointers-simple/main.c @@ -0,0 +1,53 @@ +#include + +typedef int (*fptr_t)(int); +fptr_t fun_global, fun_global_show; + +int f(int x) +{ + return x + 1; +} +int g(int x) +{ + return x; +} +int h(int x) +{ + return x - 1; +} + +int main(void) +{ + int nondet_choice; + + // Variable never written to should be top + fptr_t fun0; + fun0(5); + + fptr_t fun1 = f; + fun1(5); + + fptr_t fun2 = f; + if(nondet_choice) + fun2 = g; + fun2(5); + fptr_t fun2_show = fun2; + + fptr_t fun3; + if(nondet_choice) + fun3 = f; + else + fun3 = g; + fun3(5); + fptr_t fun3_show = fun3; + + // Global variable + if(nondet_choice) + fun_global = f; + else + fun_global = g; + fun_global(5); + fun_global_show = fun_global; + + return 0; +} diff --git a/regression/goto-analyzer/value-set-function-pointers-simple/test.desc b/regression/goto-analyzer/value-set-function-pointers-simple/test.desc new file mode 100644 index 00000000000..72616b1ca84 --- /dev/null +++ b/regression/goto-analyzer/value-set-function-pointers-simple/test.desc @@ -0,0 +1,28 @@ +CORE +main.c +--variable --structs --arrays --pointers --value-set --show --pointer-check +^file main.c line 25 function main: replacing function pointer by 2 possible targets$ +^file main.c line 28 function main: replacing function pointer by 2 possible targets$ +^file main.c line 33 function main: replacing function pointer by 2 possible targets$ +^file main.c line 41 function main: replacing function pointer by 2 possible targets$ +^file main.c line 49 function main: replacing function pointer by 2 possible targets$ +^main::1::fun0 \(\) -> TOP$ +^main::1::fun1 \(\) -> value-set-begin: ptr ->\(f\), :value-set-end$ +^main::1::fun2_show \(\) -> value-set-begin: ptr ->\([fg]\), ptr ->\([fg]\), :value-set-end$ +^main::1::fun3_show \(\) -> value-set-begin: ptr ->\([fg]\), ptr ->\([fg]\), :value-set-end$ +^fun_global_show \(\) -> value-set-begin: ptr ->\([fg]\), ptr ->\([fg]\), :value-set-end$ +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring +^main::1::fun0_show \(\) -> value-set-begin: .* :value-set-end$ +^main::1::fun1_show \(\) -> value-set-begin: .*ptr ->\(h\).* :value-set-end$ +^main::1::fun2_show \(\) -> value-set-begin: .*ptr ->\(h\).* :value-set-end$ +^main::1::fun3_show \(\) -> \{\[0\] = value-set-begin: .*ptr ->\(h\).* :value-set-end$ +^fun_global_show \(\) -> value-set-begin: .*ptr ->\(h\).* :value-set-end$ +-- +ADA-495 has been filed to fix this bug. +It fails because after the line "fun_global_show = fun_global", fun_global_show +gets the following value set: +fun_global_show () -> value-set-begin: TOP, ptr ->(g), ptr ->(f), :value-set-end +which is wrong diff --git a/regression/goto-analyzer/value-set-function-pointers-structs/main.c b/regression/goto-analyzer/value-set-function-pointers-structs/main.c new file mode 100644 index 00000000000..4e084010387 --- /dev/null +++ b/regression/goto-analyzer/value-set-function-pointers-structs/main.c @@ -0,0 +1,55 @@ +#include + +typedef int (*fptr_t)(int); + +int f(int x) +{ + return x + 1; +} +int g(int x) +{ + return x; +} +int h(int x) +{ + return x - 1; +} + +struct struct_containing_fptr +{ + int i; + fptr_t fptr; + double d; +}; + +int main(void) +{ + int nondet_choice; + + // Read from struct + struct struct_containing_fptr s0, s1; + s0.fptr = f; + s1.fptr = g; + fptr_t fun1; + if(nondet_choice) + fun1 = s0.fptr; + else + fun1 = s1.fptr; + fun1(5); + + // Write to struct + struct struct_containing_fptr s2; + if(nondet_choice) + s2.fptr = f; + else + s2.fptr = g; + s2.fptr(5); + + // Array of structs + struct struct_containing_fptr s_array[3]; + s_array[0] = s0; + s_array[1] = s1; + s_array[2] = s2; + fptr_t fun2 = (s_array + 1)->fptr; + fun2(5); +} diff --git a/regression/goto-analyzer/value-set-function-pointers-structs/test.desc b/regression/goto-analyzer/value-set-function-pointers-structs/test.desc new file mode 100644 index 00000000000..b931818ac3b --- /dev/null +++ b/regression/goto-analyzer/value-set-function-pointers-structs/test.desc @@ -0,0 +1,16 @@ +CORE +main.c +--variable --structs --arrays --pointers --value-set --show --pointer-check +^file main.c line 38 function main: replacing function pointer by 2 possible targets$ +^file main.c line 46 function main: replacing function pointer by 2 possible targets$ +^file main.c line 54 function main: replacing function pointer by 2 possible targets$ +^main::1::fun1 \(\) -> value-set-begin: ptr ->\([fg]\), ptr ->\([fg]\), :value-set-end$ +^main::1::s2 \(\) -> \{\.fptr=value-set-begin: ptr ->\([fg]\), ptr ->\([fg]\), :value-set-end\}$ +^main::1::fun2 \(\) -> value-set-begin: ptr ->\(g\), :value-set-end$ +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring +^main::1::fun1 \(\) -> value-set-begin: .*ptr ->\(h\).* :value-set-end$ +^main::1::s2 \(\) -> \{\.fptr=value-set-begin: .*ptr ->\(h\).* :value-set-end\}$ +^main::1::fun2 \(\) -> value-set-begin: .*ptr ->\(h\).* :value-set-end$ diff --git a/regression/goto-analyzer/value-set-simple/main.c b/regression/goto-analyzer/value-set-simple/main.c new file mode 100644 index 00000000000..ed3f58f2319 --- /dev/null +++ b/regression/goto-analyzer/value-set-simple/main.c @@ -0,0 +1,50 @@ +#include + +int global_int = 0; +int global_int_show = 0; + +int main(void) +{ + int nondet_choice; + + if(nondet_choice) + global_int = 1; + else + global_int = 2; + global_int_show = global_int; + + assert(global_int == 2); + assert(global_int == 1 || global_int == 2); + assert(global_int > 0); + assert(global_int > 3); + + double local_double; + + if(nondet_choice) + local_double = 1.0; + else + local_double = 2.0; + double local_double_show = local_double; + + assert(local_double == 2.0); + assert(local_double == 1.0 || local_double == 2.0); + assert(local_double > 0.0); + assert(local_double > 3.0); + + double d1 = 1.0; + double d2 = 2.0; + double *local_double_ptr; + + if(nondet_choice) + local_double_ptr = &d1; + else + local_double_ptr = &d2; + double *local_double_ptr_show = local_double_ptr; + + assert(local_double_ptr == &d2); + assert(local_double_ptr == &d1 || local_double == &d2); + assert(*local_double_ptr > 0.0); + assert(*local_double_ptr > 3.0); + + return 0; +} diff --git a/regression/goto-analyzer/value-set-simple/test_show.desc b/regression/goto-analyzer/value-set-simple/test_show.desc new file mode 100644 index 00000000000..a4e02531879 --- /dev/null +++ b/regression/goto-analyzer/value-set-simple/test_show.desc @@ -0,0 +1,10 @@ +CORE +main.c +--variable --structs --arrays --pointers --value-set --show --pointer-check +^global_int_show \(\) -> value-set-begin: [12], [12], :value-set-end$ +^main::1::local_double_show \(\) -> value-set-begin: [12]\.0, [12]\.0, :value-set-end$ +^main::1::local_double_ptr_show \(\) -> value-set-begin: ptr ->\(main::1::d[12]\), ptr ->\(main::1::d[12]\), :value-set-end$ +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/value-set-simple/test_verify.desc b/regression/goto-analyzer/value-set-simple/test_verify.desc new file mode 100644 index 00000000000..0ac106b6fbb --- /dev/null +++ b/regression/goto-analyzer/value-set-simple/test_verify.desc @@ -0,0 +1,22 @@ +KNOWNBUG +main.c +--variable --structs --arrays --pointers --value-set --verify --pointer-check +^\[main.assertion.1\] line 16 assertion global_int == 2: UNKNOWN$ +^\[main.assertion.2\] line 17 assertion global_int == 1 \|\| global_int == 2: SUCCESS$ +^\[main.assertion.3\] line 18 assertion global_int > 0: SUCCESS$ +^\[main.assertion.4\] line 19 assertion global_int > 3: FAILURE \(if reachable\)$ +^\[main.assertion.5\] line 29 assertion local_double == 2.0: UNKNOWN$ +^\[main.assertion.6\] line 30 assertion local_double == 1.0 \|\| local_double == 2.0: SUCCESS$ +^\[main.assertion.7\] line 31 assertion local_double > 0.0: SUCCESS$ +^\[main.assertion.8\] line 32 assertion local_double > 3.0: FAILURE \(if reachable\)$ +^\[main.assertion.9\] line 44 assertion local_double_ptr == &d2: UNKNOWN$ +^\[main.assertion.10\] line 45 assertion local_double_ptr == &d1 \|\| local_double == &d2: SUCCESS$ +^\[main.assertion.11\] line 46 assertion \*local_double_ptr > 0.0: SUCCESS$ +^\[main.assertion.12\] line 47 assertion \*local_double_ptr > 3.0: FAILURE \(if reachable\)$ +^Summary: 6 pass, 3 fail if reachable, 3 unknown$ +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring +-- +ADA-494 has been filed to fix this. diff --git a/regression/goto-analyzer/value-set-structs/main.c b/regression/goto-analyzer/value-set-structs/main.c new file mode 100644 index 00000000000..422534487e2 --- /dev/null +++ b/regression/goto-analyzer/value-set-structs/main.c @@ -0,0 +1,67 @@ +#include + +struct my_struct +{ + int i; + double d; + char str[2]; +}; + +int main(void) +{ + int nondet_choice, nondet_choice2; + + struct my_struct s; + + if(nondet_choice) + s.d = 1.0; + else + s.d = 2.0; + + if(nondet_choice) + { + s.str[0] = 'x'; + s.str[1] = '\n'; + } + else + { + s.str[0] = 'y'; + s.str[1] = '\n'; + } + + struct my_struct s_show = s; + + assert(s.i == 0); + + assert(s.d == 1.0); + assert(s.d == 1.0 || s.d == 2.0); + assert(s.d > 0.0); + assert(s.d > 10.0); + + assert(s.str[0] == 'x'); + assert(s.str[0] == 'x' || s.str[0] == 'y'); + assert(s.str[1] == '\n'); + + struct my_struct t = {1, 3.0, {'z', '\n'}}; + struct my_struct u; + + if(nondet_choice2) + u = s; + else + u = t; + + struct my_struct u_show = u; + + assert(u.i == 1); + + assert(u.d == 3.0); + assert(u.d == 1.0 || u.d == 2.0 || u.d == 3.0); + assert(u.d > 0.0); + assert(u.d > 10.0); + + assert(u.str[0] == 'z'); + assert(u.str[0] == 'x' || u.str[0] == 'y' || u.str[0] == 'z'); + assert(u.str[1] == '\n'); + + return 0; +} diff --git a/regression/goto-analyzer/value-set-structs/test_show.desc b/regression/goto-analyzer/value-set-structs/test_show.desc new file mode 100644 index 00000000000..a3533ea2449 --- /dev/null +++ b/regression/goto-analyzer/value-set-structs/test_show.desc @@ -0,0 +1,10 @@ +CORE +main.c +--variable --structs --arrays --pointers --value-set --show --pointer-check +activate-multi-line-match +main::1::s_show \(\) -> \{\.d=value-set-begin: [12]\.0, [12]\.0, :value-set-end, \.str=\{\[0\] = value-set-begin: '[xy]', '[xy]', :value-set-end\n\[1\] = value-set-begin: '\\n', :value-set-end +main::1::u_show \(\) -> \{\.d=value-set-begin: [123]\.0, [123].0, [123]\.0, :value-set-end, \.str=\{\[0\] = value-set-begin: '[xyz]', '[xyz]', '[xyz]', :value-set-end\n\[1\] = value-set-begin: '\\n', :value-set-end +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/value-set-structs/test_verify.desc b/regression/goto-analyzer/value-set-structs/test_verify.desc new file mode 100644 index 00000000000..5833417dd35 --- /dev/null +++ b/regression/goto-analyzer/value-set-structs/test_verify.desc @@ -0,0 +1,26 @@ +KNOWNBUG +main.c +--variable --structs --arrays --pointers --value-set --verify --pointer-check +^\[main\.assertion\.1\] line 33 assertion s\.i == 0: UNKNOWN$ +^\[main\.assertion\.2\] line 35 assertion s\.d == 1.0: UNKNOWN$ +^\[main\.assertion\.3\] line 36 assertion s\.d == 1.0 \|\| s.d == 2.0: SUCCESS$ +^\[main\.assertion\.4\] line 37 assertion s\.d > 0.0: SUCCESS$ +^\[main\.assertion\.5\] line 38 assertion s\.d > 10.0: FAILURE \(if reachable\)$ +^\[main\.assertion\.6\] line 40 assertion s\.str\[0\] == 'x': UNKNOWN$ +^\[main\.assertion\.7\] line 41 assertion s\.str\[0\] == 'x' \|\| s.str\[0\] == 'y': SUCCESS$ +^\[main\.assertion\.8\] line 42 assertion s\.str\[1\] == '\\n': SUCCESS$ +^\[main\.assertion\.9\] line 55 assertion u\.i == 1: UNKNOWN$ +^\[main\.assertion\.10\] line 57 assertion u\.d == 3.0: UNKNOWN$ +^\[main\.assertion\.11\] line 58 assertion u\.d == 1.0 \|\| u\.d == 2.0 \|\| u\.d == 3.0: SUCCESS$ +^\[main\.assertion\.12\] line 59 assertion u\.d > 0.0: SUCCESS$ +^\[main\.assertion\.13\] line 60 assertion u\.d > 10.0: FAILURE \(if reachable\)$ +^\[main\.assertion\.14\] line 62 assertion u\.str\[0\] == 'z': UNKNOWN$ +^\[main\.assertion\.15\] line 63 assertion u\.str\[0\] == 'x' \|\| u.str\[0\] == 'y' \|\| u.str\[0\] == 'z': SUCCESS$ +^\[main\.assertion\.16\] line 64 assertion u\.str\[1\] == '\\n': SUCCESS$ +^Summary: 8 pass, 2 fail if reachable, 6 unknown$ +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring +-- +ADA-494 has been filed to fix this. diff --git a/unit/analyses/variable-sensitivity/eval.cpp b/unit/analyses/variable-sensitivity/eval.cpp new file mode 100644 index 00000000000..91c2cdd7d89 --- /dev/null +++ b/unit/analyses/variable-sensitivity/eval.cpp @@ -0,0 +1,97 @@ +// Copyright 2016-2020 Diffblue Limited. All Rights Reserved. + +#include +#include +#include +#include +#include +#include + +static symbolt simple_symbol(const irep_idt &identifier, const typet &type) +{ + symbolt b1; + b1.name = b1.base_name = b1.pretty_name = identifier; + b1.type = type; + return b1; +} + +SCENARIO("eval", "[core]") +{ + GIVEN("An environment with intervals domain") + { + variable_sensitivity_object_factoryt::instance().set_options( + vsd_configt::intervals()); + abstract_environmentt environment; + + symbol_tablet symbol_table; + namespacet ns{symbol_table}; + + signedbv_typet number_type{32}; + const auto &b1 = simple_symbol("b1", number_type); + symbol_table.add(b1); + + WHEN("Evaluating expression with an unknown value") + { + // b1 == 0 ? 1 : 0 + if_exprt condition{ + equal_exprt{b1.symbol_expr(), from_integer(0, number_type)}, + from_integer(1, number_type), + from_integer(0, number_type)}; + + const auto result = environment.eval(condition, ns); + + THEN("Should get a wrapped range of 0..1") + { + REQUIRE( + std::dynamic_pointer_cast(result)); + REQUIRE_FALSE(result->is_top()); + REQUIRE_FALSE(result->is_bottom()); + const auto unwrapped = + std::dynamic_pointer_cast(result) + ->unwrap_context(); + auto result_as_interval = + std::dynamic_pointer_cast(unwrapped); + REQUIRE(result_as_interval); + REQUIRE( + result_as_interval->get_interval().get_lower() == + from_integer(0, number_type)); + REQUIRE( + result_as_interval->get_interval().get_upper() == + from_integer(1, number_type)); + } + + WHEN("Assigning the symbol a value") + { + // b1 = 0 + environment.assign( + b1.symbol_expr(), + variable_sensitivity_object_factoryt::instance().get_abstract_object( + number_type, + false, + false, + from_integer(0, number_type), + environment, + ns), + ns); + + const auto result_after_assignment = environment.eval(condition, ns); + + THEN("Should get a wrapped interval of one element") + { + REQUIRE(std::dynamic_pointer_cast( + result_after_assignment)); + const auto unwrapped = + std::dynamic_pointer_cast( + result_after_assignment) + ->unwrap_context(); + auto result_as_interval = + std::dynamic_pointer_cast( + unwrapped); + REQUIRE(result_as_interval); + REQUIRE( + result_as_interval->to_constant() == from_integer(1, number_type)); + } + } + } + } +} From 7ec8050f0dab132c55240990b15eb8a45b2d087d Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Mon, 20 Apr 2020 10:42:34 +0100 Subject: [PATCH 298/342] Fix test and add reference to github issue. --- .../value-set-function-pointers-simple/test.desc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/regression/goto-analyzer/value-set-function-pointers-simple/test.desc b/regression/goto-analyzer/value-set-function-pointers-simple/test.desc index 72616b1ca84..406e42cf511 100644 --- a/regression/goto-analyzer/value-set-function-pointers-simple/test.desc +++ b/regression/goto-analyzer/value-set-function-pointers-simple/test.desc @@ -8,9 +8,9 @@ main.c ^file main.c line 49 function main: replacing function pointer by 2 possible targets$ ^main::1::fun0 \(\) -> TOP$ ^main::1::fun1 \(\) -> value-set-begin: ptr ->\(f\), :value-set-end$ -^main::1::fun2_show \(\) -> value-set-begin: ptr ->\([fg]\), ptr ->\([fg]\), :value-set-end$ +^main::1::fun2_show \(\) -> value-set-begin: (TOP, )?ptr ->\([fg]\), (TOP, )?ptr ->\([fg]\), (TOP, )?:value-set-end$ ^main::1::fun3_show \(\) -> value-set-begin: ptr ->\([fg]\), ptr ->\([fg]\), :value-set-end$ -^fun_global_show \(\) -> value-set-begin: ptr ->\([fg]\), ptr ->\([fg]\), :value-set-end$ +^fun_global_show \(\) -> value-set-begin: (TOP, )?ptr ->\([fg]\), (TOP, )?ptr ->\([fg]\), (TOP, )?:value-set-end$ ^EXIT=0$ ^SIGNAL=0$ -- @@ -21,8 +21,6 @@ main.c ^main::1::fun3_show \(\) -> \{\[0\] = value-set-begin: .*ptr ->\(h\).* :value-set-end$ ^fun_global_show \(\) -> value-set-begin: .*ptr ->\(h\).* :value-set-end$ -- -ADA-495 has been filed to fix this bug. -It fails because after the line "fun_global_show = fun_global", fun_global_show -gets the following value set: -fun_global_show () -> value-set-begin: TOP, ptr ->(g), ptr ->(f), :value-set-end -which is wrong +These TOP values in the sets shouldn't exist. +They're caused by a quirk in the implementation, see +https://github.com/diffblue/cbmc/issues/5307 which has been filed to fix this bug. From 8fc8986819b202245ba435b572dd8a3cca73ae5b Mon Sep 17 00:00:00 2001 From: Fotis Koutoulakis Date: Thu, 30 Apr 2020 14:44:57 +0100 Subject: [PATCH 299/342] Make variable_sensitivity_domaint::eval public from protected --- src/analyses/variable-sensitivity/variable_sensitivity_domain.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index a1c9d9e1033..3f88ca4988d 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -114,7 +114,6 @@ class variable_sensitivity_domaint:public ai_domain_baset bool is_bottom() const override; bool is_top() const override; -protected: virtual abstract_object_pointert eval( const exprt &expr, const namespacet &ns) const { From bb211d1acb1751b23a8ffa5a1bf0588bb8881ebe Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Fri, 22 May 2020 10:07:31 +0100 Subject: [PATCH 300/342] Add stub implementations for value set classes --- src/analyses/Makefile | 6 +- .../value_set_abstract_value.cpp | 14 +++++ .../value_set_abstract_value.h | 27 +++++++++ .../value_set_array_abstract_object.cpp | 56 +++++++++++++++++ .../value_set_array_abstract_object.h | 54 +++++++++++++++++ .../value_set_pointer_abstract_object.cpp | 60 +++++++++++++++++++ .../value_set_pointer_abstract_object.h | 54 +++++++++++++++++ unit/Makefile | 3 + .../value_set/abstract_value.cpp | 19 ++++++ .../value_set/array_abstract_object.cpp | 21 +++++++ .../value_set/module_dependencies.txt | 3 + .../value_set/pointer_abstract_object.cpp | 20 +++++++ .../value_set/value_set_test_common.h | 18 ++++++ 13 files changed, 354 insertions(+), 1 deletion(-) create mode 100644 src/analyses/variable-sensitivity/value_set_abstract_value.cpp create mode 100644 src/analyses/variable-sensitivity/value_set_abstract_value.h create mode 100644 src/analyses/variable-sensitivity/value_set_array_abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/value_set_array_abstract_object.h create mode 100644 src/analyses/variable-sensitivity/value_set_pointer_abstract_object.cpp create mode 100644 src/analyses/variable-sensitivity/value_set_pointer_abstract_object.h create mode 100644 unit/analyses/variable-sensitivity/value_set/abstract_value.cpp create mode 100644 unit/analyses/variable-sensitivity/value_set/array_abstract_object.cpp create mode 100644 unit/analyses/variable-sensitivity/value_set/module_dependencies.txt create mode 100644 unit/analyses/variable-sensitivity/value_set/pointer_abstract_object.cpp create mode 100644 unit/analyses/variable-sensitivity/value_set/value_set_test_common.h diff --git a/src/analyses/Makefile b/src/analyses/Makefile index bbdcd71dfa7..ceef596a30a 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -54,7 +54,11 @@ SRC = ai.cpp \ variable-sensitivity/value_set_abstract_object.cpp \ variable-sensitivity/variable_sensitivity_dependence_graph.cpp \ variable-sensitivity/interval_abstract_value.cpp \ - variable-sensitivity/interval_array_abstract_object.cpp \ + variable-sensitivity/interval_array_abstract_object.cpp \ + variable-sensitivity/value_set_abstract_object.cpp \ + variable-sensitivity/value_set_abstract_value.cpp \ + variable-sensitivity/value_set_pointer_abstract_object.cpp \ + variable-sensitivity/value_set_array_abstract_object.cpp \ # Empty last line INCLUDES= -I .. diff --git a/src/analyses/variable-sensitivity/value_set_abstract_value.cpp b/src/analyses/variable-sensitivity/value_set_abstract_value.cpp new file mode 100644 index 00000000000..5d80f5a1ad2 --- /dev/null +++ b/src/analyses/variable-sensitivity/value_set_abstract_value.cpp @@ -0,0 +1,14 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity variable-sensitivity-value-set + + Author: Diffblue Ltd. + +\*******************************************************************/ + +#include "value_set_abstract_value.h" + +value_set_abstract_valuet::value_set_abstract_valuet(const typet &type) + : abstract_valuet(type) +{ +} diff --git a/src/analyses/variable-sensitivity/value_set_abstract_value.h b/src/analyses/variable-sensitivity/value_set_abstract_value.h new file mode 100644 index 00000000000..91731b7e43d --- /dev/null +++ b/src/analyses/variable-sensitivity/value_set_abstract_value.h @@ -0,0 +1,27 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity variable-sensitivity-value-set + + Author: Diffblue Ltd. + +\*******************************************************************/ + +/// \file +/// Value sets for primitives + +// NOLINTNEXTLINE(whitespace/line_length) +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_ABSTRACT_VALUE_H +// NOLINTNEXTLINE(whitespace/line_length) +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_ABSTRACT_VALUE_H + +#include "abstract_value.h" + +class value_set_abstract_valuet : public abstract_valuet +{ +public: + explicit value_set_abstract_valuet(const typet &type); + CLONE +}; + +// NOLINTNEXTLINE(whitespace/line_length) +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_ABSTRACT_VALUE_H diff --git a/src/analyses/variable-sensitivity/value_set_array_abstract_object.cpp b/src/analyses/variable-sensitivity/value_set_array_abstract_object.cpp new file mode 100644 index 00000000000..57770c6fbf3 --- /dev/null +++ b/src/analyses/variable-sensitivity/value_set_array_abstract_object.cpp @@ -0,0 +1,56 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity variable-sensitivity-value-set + + Author: Diffblue Ltd. + +\*******************************************************************/ + +#include "value_set_array_abstract_object.h" + +value_set_array_abstract_objectt::value_set_array_abstract_objectt( + const typet &type) + : array_abstract_objectt(type) +{ +} + +abstract_object_pointert value_set_array_abstract_objectt::read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const +{ + return array_abstract_objectt::read(env, specifier, ns); +} + +abstract_object_pointert value_set_array_abstract_objectt::write( + abstract_environmentt &environment, + const namespacet &ns, + std::stack stack, + const exprt &specifier, + abstract_object_pointert value, + bool merging_write) const +{ + return array_abstract_objectt::write( + environment, ns, stack, specifier, value, merging_write); +} + +abstract_object_pointert value_set_array_abstract_objectt::read_index( + const abstract_environmentt &env, + const index_exprt &index, + const namespacet &ns) const +{ + return array_abstract_objectt::read_index(env, index, ns); +} + +sharing_ptrt +value_set_array_abstract_objectt::write_index( + abstract_environmentt &environment, + const namespacet &ns, + std::stack stack, + const index_exprt &index_expr, + abstract_object_pointert value, + bool merging_write) const +{ + return array_abstract_objectt::write_index( + environment, ns, stack, index_expr, value, merging_write); +} diff --git a/src/analyses/variable-sensitivity/value_set_array_abstract_object.h b/src/analyses/variable-sensitivity/value_set_array_abstract_object.h new file mode 100644 index 00000000000..3318e6dece5 --- /dev/null +++ b/src/analyses/variable-sensitivity/value_set_array_abstract_object.h @@ -0,0 +1,54 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity variable-sensitivity-value-set + + Author: Diffblue Ltd. + +\*******************************************************************/ + +/// \file +/// Arrays with value sets as indices + +// NOLINTNEXTLINE(whitespace/line_length) +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_ARRAY_ABSTRACT_OBJECT_H +// NOLINTNEXTLINE(whitespace/line_length) +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_ARRAY_ABSTRACT_OBJECT_H + +#include "array_abstract_object.h" + +class value_set_array_abstract_objectt : public array_abstract_objectt +{ +public: + explicit value_set_array_abstract_objectt(const typet &type); + + abstract_object_pointert read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const override; + + abstract_object_pointert write( + abstract_environmentt &environment, + const namespacet &ns, + std::stack stack, + const exprt &specifier, + abstract_object_pointert value, + bool merging_write) const override; + + CLONE +protected: + abstract_object_pointert read_index( + const abstract_environmentt &env, + const index_exprt &index, + const namespacet &ns) const override; + + sharing_ptrt write_index( + abstract_environmentt &environment, + const namespacet &ns, + std::stack stack, + const index_exprt &index_expr, + abstract_object_pointert value, + bool merging_write) const override; +}; + +// NOLINTNEXTLINE(whitespace/line_length) +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_ARRAY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/value_set_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/value_set_pointer_abstract_object.cpp new file mode 100644 index 00000000000..60213bb724a --- /dev/null +++ b/src/analyses/variable-sensitivity/value_set_pointer_abstract_object.cpp @@ -0,0 +1,60 @@ + +/*******************************************************************\ + + Module: analyses variable-sensitivity variable-sensitivity-value-set + + Author: Diffblue Ltd. + +\*******************************************************************/ + +#include "value_set_pointer_abstract_object.h" + +abstract_object_pointert +value_set_pointer_abstract_objectt::merge(abstract_object_pointert other) const +{ + return shared_from_this(); +} + +abstract_object_pointert value_set_pointer_abstract_objectt::read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const +{ + return pointer_abstract_objectt::read(env, specifier, ns); +} + +abstract_object_pointert value_set_pointer_abstract_objectt::write( + abstract_environmentt &environment, + const namespacet &ns, + std::stack stack, + const exprt &specifier, + abstract_object_pointert value, + bool merging_write) const +{ + return pointer_abstract_objectt::write( + environment, ns, stack, specifier, value, merging_write); +} + +value_set_pointer_abstract_objectt::value_set_pointer_abstract_objectt( + const typet &type) + : pointer_abstract_objectt(type) +{ +} +abstract_object_pointert value_set_pointer_abstract_objectt::read_dereference( + const abstract_environmentt &env, + const namespacet &ns) const +{ + return pointer_abstract_objectt::read_dereference(env, ns); +} + +sharing_ptrt +value_set_pointer_abstract_objectt::write_dereference( + abstract_environmentt &environment, + const namespacet &ns, + std::stack stack, + abstract_object_pointert value, + bool merging_write) const +{ + return pointer_abstract_objectt::write_dereference( + environment, ns, stack, value, merging_write); +} diff --git a/src/analyses/variable-sensitivity/value_set_pointer_abstract_object.h b/src/analyses/variable-sensitivity/value_set_pointer_abstract_object.h new file mode 100644 index 00000000000..7dd04d4a43b --- /dev/null +++ b/src/analyses/variable-sensitivity/value_set_pointer_abstract_object.h @@ -0,0 +1,54 @@ +/*******************************************************************\ + + Module: analyses variable-sensitivity variable-sensitivity-value-set + + Author: Diffblue Ltd. + +\*******************************************************************/ + +/// \file +/// Pointers pointing to a limited-size set of possible targets + +// NOLINTNEXTLINE(whitespace/line_length) +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_POINTER_ABSTRACT_OBJECT_H +// NOLINTNEXTLINE(whitespace/line_length) +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_POINTER_ABSTRACT_OBJECT_H + +#include "pointer_abstract_object.h" + +class value_set_pointer_abstract_objectt : public pointer_abstract_objectt +{ +public: + explicit value_set_pointer_abstract_objectt(const typet &type); + + abstract_object_pointert merge(abstract_object_pointert other) const override; + + abstract_object_pointert read( + const abstract_environmentt &env, + const exprt &specifier, + const namespacet &ns) const override; + + abstract_object_pointert write( + abstract_environmentt &environment, + const namespacet &ns, + std::stack stack, + const exprt &specifier, + abstract_object_pointert value, + bool merging_write) const override; + + CLONE +protected: + abstract_object_pointert read_dereference( + const abstract_environmentt &env, + const namespacet &ns) const override; + + sharing_ptrt write_dereference( + abstract_environmentt &environment, + const namespacet &ns, + std::stack stack, + abstract_object_pointert value, + bool merging_write) const override; +}; + +// NOLINTNEXTLINE(whitespace/line_length) +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_POINTER_ABSTRACT_OBJECT_H diff --git a/unit/Makefile b/unit/Makefile index d5a669574e7..c4aa28ca58d 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -20,6 +20,9 @@ SRC += analyses/ai/ai.cpp \ analyses/variable-sensitivity/interval_abstract_value/meet.cpp \ analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp \ analyses/variable-sensitivity/last_written_location.cpp \ + analyses/variable-sensitivity/value_set/abstract_value.cpp \ + analyses/variable-sensitivity/value_set/array_abstract_object.cpp \ + analyses/variable-sensitivity/value_set/pointer_abstract_object.cpp \ ansi-c/max_malloc_size.cpp \ ansi-c/type2name.cpp \ big-int/big-int.cpp \ diff --git a/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp b/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp new file mode 100644 index 00000000000..a2caf5344d3 --- /dev/null +++ b/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp @@ -0,0 +1,19 @@ +/*******************************************************************\ + +Module: Unit tests for value set abstract values + +Author: Diffblue Ltd. + +\*******************************************************************/ + +#include "value_set_test_common.h" +#include + +TEST_CASE( + "A value set abstract object created from type is top", + VALUE_SET_TEST_TAGS) +{ + value_set_abstract_valuet abstract_value(signedbv_typet{32}); + REQUIRE(abstract_value.is_top()); + REQUIRE(!abstract_value.is_bottom()); +} diff --git a/unit/analyses/variable-sensitivity/value_set/array_abstract_object.cpp b/unit/analyses/variable-sensitivity/value_set/array_abstract_object.cpp new file mode 100644 index 00000000000..f798d441b77 --- /dev/null +++ b/unit/analyses/variable-sensitivity/value_set/array_abstract_object.cpp @@ -0,0 +1,21 @@ +/*******************************************************************\ + +Module: Unit tests for value set array abstract values + +Author: Diffblue Ltd. + +\*******************************************************************/ + +#include "value_set_test_common.h" +#include +#include + +TEST_CASE( + "A value set array abstract object created from type is top", + VALUE_SET_TEST_TAGS) +{ + value_set_array_abstract_objectt abstract_object{ + array_typet{signedbv_typet{32}, from_integer(1, unsignedbv_typet{32})}}; + REQUIRE(abstract_object.is_top()); + REQUIRE(!abstract_object.is_bottom()); +} diff --git a/unit/analyses/variable-sensitivity/value_set/module_dependencies.txt b/unit/analyses/variable-sensitivity/value_set/module_dependencies.txt new file mode 100644 index 00000000000..ac96be3c1ef --- /dev/null +++ b/unit/analyses/variable-sensitivity/value_set/module_dependencies.txt @@ -0,0 +1,3 @@ +analyses +testing-utils +util diff --git a/unit/analyses/variable-sensitivity/value_set/pointer_abstract_object.cpp b/unit/analyses/variable-sensitivity/value_set/pointer_abstract_object.cpp new file mode 100644 index 00000000000..a796d0a898e --- /dev/null +++ b/unit/analyses/variable-sensitivity/value_set/pointer_abstract_object.cpp @@ -0,0 +1,20 @@ +/*******************************************************************\ + +Module: Unit tests for value set pointer abstract objects + +Author: Diffblue Ltd. + +\*******************************************************************/ + +#include "value_set_test_common.h" +#include + +TEST_CASE( + "A value set pointer abstract object created from type is top", + VALUE_SET_TEST_TAGS) +{ + value_set_pointer_abstract_objectt abstract_object( + pointer_typet(signedbv_typet{32}, 32)); + REQUIRE(abstract_object.is_top()); + REQUIRE(!abstract_object.is_bottom()); +} diff --git a/unit/analyses/variable-sensitivity/value_set/value_set_test_common.h b/unit/analyses/variable-sensitivity/value_set/value_set_test_common.h new file mode 100644 index 00000000000..55e23d02f39 --- /dev/null +++ b/unit/analyses/variable-sensitivity/value_set/value_set_test_common.h @@ -0,0 +1,18 @@ +/*******************************************************************\ + +Module: Unit tests for value set pointer abstract objects + +Author: Diffblue Ltd. + +\*******************************************************************/ + +// NOLINTNEXTLINE(whitespace/line_length) +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_VALUE_SET_TEST_COMMON_H +// NOLINTNEXTLINE(whitespace/line_length) +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_VALUE_SET_TEST_COMMON_H + +#include +#define VALUE_SET_TEST_TAGS "[core][analyses][variable-sensitivity][value-set]" + +// NOLINTNEXTLINE(whitespace/line_length) +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VALUE_SET_VALUE_SET_TEST_COMMON_H From 22c7be1cd0c0740e94e73427cd5fc93337772727 Mon Sep 17 00:00:00 2001 From: martin Date: Sat, 4 Jul 2020 00:09:56 +0100 Subject: [PATCH 301/342] clang-format everything --- .../partial-simplify-array/main.c | 4 +- .../simplify-complex-expression/main.c | 3 +- .../simplify-lhs-array-pointers-index/main.c | 4 +- .../simplify-lhs-dereference/main.c | 13 +- .../simplify-lhs-member/main.c | 14 +- .../main.c | 12 +- .../constant_assertions_01/main.c | 4 +- .../constant_assertions_02/main.c | 4 +- .../constant_propagation_01/main.c | 3 +- .../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_06/main.c | 4 +- .../constant_propagation_08/main.c | 2 +- .../constant_propagation_09/main.c | 2 +- .../constant_propagation_10/main.c | 2 +- .../constant_propagation_11/main.c | 2 +- .../constant_propagation_12/main.c | 2 +- .../constant_propagation_13/main.c | 2 +- .../constant_propagation_14/main.c | 4 +- .../constant_propagation_15/main.c | 2 +- .../constant_propagation_17/main.c | 4 +- regression/goto-analyzer/demo/main.c | 58 +-- regression/goto-analyzer/intervals_01/main.c | 14 +- regression/goto-analyzer/intervals_02/main.c | 2 +- regression/goto-analyzer/intervals_04/main.c | 2 +- regression/goto-analyzer/intervals_05/main.c | 2 +- regression/goto-analyzer/intervals_08/main.c | 2 +- regression/goto-analyzer/intervals_09/main.c | 2 +- regression/goto-analyzer/intervals_10/main.c | 10 +- regression/goto-analyzer/intervals_11/main.c | 8 +- regression/goto-analyzer/intervals_13/main.c | 14 +- regression/goto-analyzer/intervals_14/main.c | 8 +- regression/goto-analyzer/intervals_15/main.c | 4 +- regression/goto-analyzer/intervals_16/main.c | 4 +- .../minimal_reproducer_for_struct_problem.c | 22 +- .../sensitivity-function-call-array/main.c | 10 +- .../sensitivity-function-call-opaque/main.c | 20 +- .../sensitivity-function-call-pointer/main.c | 16 +- .../main.c | 8 +- .../sensitivity-function-call-varargs/main.c | 12 +- .../sensitivity_dependency_arrays.c | 34 +- .../sensitivity_dependency_pointers.c | 20 +- .../sensitivity_dependency_structs.c | 40 +- .../sensitivity_dependency_variables.c | 42 +- .../array_of_array_sensitivity_tests.c | 132 +++--- .../array_of_pointer_sensitivity_tests.c | 142 +++---- .../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 | 50 +-- .../pointer_to_pointer_sensitivity_tests.c | 12 +- .../pointer_to_struct_sensitivity_tests.c | 50 +-- .../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 +- .../main.c | 11 +- .../data-dependency-context.c | 13 +- .../struct-initialization.c | 71 ++-- .../unreachable_assertions_01/main.c | 26 +- .../main.c | 10 +- .../main.c | 28 +- .../main.c | 33 +- .../main.c | 40 +- .../main.c | 44 +- .../main.c | 44 +- .../main.c | 44 +- .../main.c | 53 +-- .../main.c | 9 +- .../main.c | 9 +- .../variable-sensitivity-bug-01/main.c | 12 +- .../variable-sensitivity-bug-02/main.c | 24 +- .../variable-sensitivity-bug-03/main.c | 4 +- .../main.c | 1 - .../main.c | 11 +- .../file1.c | 7 +- .../file2.c | 4 +- .../main.c | 13 +- .../file1.c | 7 +- .../file2.c | 4 +- .../main.c | 13 +- .../main.c | 4 +- .../main.c | 2 +- .../main.c | 4 +- .../main.c | 16 +- .../main.c | 7 +- .../main.c | 4 +- .../main.c | 2 +- .../main.c | 7 +- .../write-stack-address-of.c | 22 +- .../abstract_enviroment.cpp | 184 +++++---- .../abstract_enviroment.h | 22 +- .../variable-sensitivity/abstract_object.cpp | 68 ++-- .../variable-sensitivity/abstract_object.h | 119 +++--- .../variable-sensitivity/abstract_value.cpp | 20 +- .../variable-sensitivity/abstract_value.h | 7 +- .../array_abstract_object.cpp | 40 +- .../array_abstract_object.h | 13 +- .../constant_abstract_value.cpp | 46 ++- .../constant_abstract_value.h | 25 +- .../constant_array_abstract_object.cpp | 73 ++-- .../constant_array_abstract_object.h | 39 +- .../constant_pointer_abstract_object.cpp | 89 ++-- .../constant_pointer_abstract_object.h | 23 +- .../context_abstract_object.cpp | 32 +- .../context_abstract_object.h | 30 +- .../data_dependency_context.cpp | 65 +-- .../data_dependency_context.h | 38 +- .../full_struct_abstract_object.cpp | 94 ++--- .../full_struct_abstract_object.h | 20 +- .../interval_abstract_value.cpp | 97 +++-- .../interval_abstract_value.h | 19 +- .../interval_array_abstract_object.cpp | 6 +- .../pointer_abstract_object.cpp | 49 ++- .../pointer_abstract_object.h | 13 +- .../struct_abstract_object.cpp | 37 +- .../struct_abstract_object.h | 11 +- .../union_abstract_object.cpp | 28 +- .../union_abstract_object.h | 47 ++- .../variable_sensitivity_dependence_graph.cpp | 279 +++++++------ .../variable_sensitivity_dependence_graph.h | 89 ++-- .../variable_sensitivity_domain.cpp | 251 ++++++------ .../variable_sensitivity_domain.h | 22 +- .../variable_sensitivity_object_factory.cpp | 47 ++- .../variable_sensitivity_object_factory.h | 67 +-- .../write_location_context.cpp | 106 +++-- .../write_location_context.h | 54 ++- .../variable-sensitivity/write_stack.cpp | 95 +++-- .../variable-sensitivity/write_stack.h | 7 +- .../write_stack_entry.cpp | 22 +- .../variable-sensitivity/write_stack_entry.h | 12 +- .../abstract_object/merge.cpp | 55 +-- .../constant_abstract_value/merge.cpp | 226 +++++------ .../constant_array_abstract_object/merge.cpp | 357 ++++++++-------- .../full_struct_abstract_object/merge.cpp | 380 +++++++++--------- .../last_written_location.cpp | 33 +- 140 files changed, 2668 insertions(+), 2516 deletions(-) diff --git a/regression/goto-analyzer-simplify/partial-simplify-array/main.c b/regression/goto-analyzer-simplify/partial-simplify-array/main.c index dce6dd9de42..bf80fa1399a 100644 --- a/regression/goto-analyzer-simplify/partial-simplify-array/main.c +++ b/regression/goto-analyzer-simplify/partial-simplify-array/main.c @@ -2,6 +2,6 @@ extern int arr[]; void main() { - int index=0; - int j=arr[index]; + int index = 0; + int j = arr[index]; } diff --git a/regression/goto-analyzer-simplify/simplify-complex-expression/main.c b/regression/goto-analyzer-simplify/simplify-complex-expression/main.c index 094de4b8134..3f0df80ad1a 100644 --- a/regression/goto-analyzer-simplify/simplify-complex-expression/main.c +++ b/regression/goto-analyzer-simplify/simplify-complex-expression/main.c @@ -4,7 +4,8 @@ int main(void) { int r = nondet_int(); r = r + 1; - if(r == 2) { + if(r == 2) + { return 1; } return 0; diff --git a/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/main.c b/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/main.c index 8883f03521e..db8b61e792b 100644 --- a/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/main.c +++ b/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/main.c @@ -4,7 +4,7 @@ void main() int symbol_b; int nondet; - int * nondet_pointer; + int *nondet_pointer; if(nondet > 0) { nondet_pointer = &symbol_a; @@ -14,7 +14,7 @@ void main() nondet_pointer = &symbol_b; } - int *arr[] = { &symbol_a, &symbol_b, nondet_pointer }; + int *arr[] = {&symbol_a, &symbol_b, nondet_pointer}; // Simplify the pointer *arr[0] = 1; diff --git a/regression/goto-analyzer-simplify/simplify-lhs-dereference/main.c b/regression/goto-analyzer-simplify/simplify-lhs-dereference/main.c index 26a245a56f2..5b3be78d13c 100644 --- a/regression/goto-analyzer-simplify/simplify-lhs-dereference/main.c +++ b/regression/goto-analyzer-simplify/simplify-lhs-dereference/main.c @@ -2,22 +2,21 @@ void main() { int symbol; - int *pointer=&symbol; + int *pointer = &symbol; // Simplify - *pointer=5; + *pointer = 5; int nondet; - if(nondet>0) + if(nondet > 0) { - pointer=&nondet; + pointer = &nondet; } else { - pointer=&symbol; + pointer = &symbol; } // No simplification - *pointer=6; - + *pointer = 6; } diff --git a/regression/goto-analyzer-simplify/simplify-lhs-member/main.c b/regression/goto-analyzer-simplify/simplify-lhs-member/main.c index 7889998318e..d375cf28e26 100644 --- a/regression/goto-analyzer-simplify/simplify-lhs-member/main.c +++ b/regression/goto-analyzer-simplify/simplify-lhs-member/main.c @@ -1,6 +1,6 @@ struct test_struct { - int * pointer_component; + int *pointer_component; int array[5]; }; @@ -12,23 +12,23 @@ void main() // Simplify a pointer inside a struct int symbol; - value.pointer_component=&symbol; + value.pointer_component = &symbol; // Simplify - *value.pointer_component=5; + *value.pointer_component = 5; int nondet; - if(nondet>0) + if(nondet > 0) { - value.pointer_component=&nondet; + value.pointer_component = &nondet; } else { - value.pointer_component=&symbol; + value.pointer_component = &symbol; } // No simplification - *value.pointer_component=6; + *value.pointer_component = 6; // Simplify an array diff --git a/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/main.c b/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/main.c index a7e9b0d950e..419434e47eb 100644 --- a/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/main.c +++ b/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/main.c @@ -2,20 +2,20 @@ void main() { int array[] = {1, 2, 3, 4, 5}; - int *pointer=array; + int *pointer = array; // Simplify -> array[0] = 5 - *pointer=5; + *pointer = 5; int nondet; - pointer[nondet]=6; + pointer[nondet] = 6; // TODO: Currently writing to an offset pointer sets the domain to top // so recreate the variables to reign the domain back in // This will be addressed by diffblue/cbmc-toyota#118 int new_array[] = {1, 2, 3, 4, 5}; - int * new_pointer=new_array; + int *new_pointer = new_array; - int constant=1; - new_pointer[constant]=7; + int constant = 1; + new_pointer[constant] = 7; } diff --git a/regression/goto-analyzer/constant_assertions_01/main.c b/regression/goto-analyzer/constant_assertions_01/main.c index 3a767276c2a..2eb59ab12a2 100644 --- a/regression/goto-analyzer/constant_assertions_01/main.c +++ b/regression/goto-analyzer/constant_assertions_01/main.c @@ -1,8 +1,8 @@ #include -int nondet_int (void); +int nondet_int(void); -int main (int argc, char **argv) +int main(int argc, char **argv) { int x = nondet_int(); int y = nondet_int(); diff --git a/regression/goto-analyzer/constant_assertions_02/main.c b/regression/goto-analyzer/constant_assertions_02/main.c index 889d980d200..d77496524ea 100644 --- a/regression/goto-analyzer/constant_assertions_02/main.c +++ b/regression/goto-analyzer/constant_assertions_02/main.c @@ -1,8 +1,8 @@ #include -int nondet_int (void); +int nondet_int(void); -int main (int argc, char **argv) +int main(int argc, char **argv) { int x = nondet_int(); int y = nondet_int(); diff --git a/regression/goto-analyzer/constant_propagation_01/main.c b/regression/goto-analyzer/constant_propagation_01/main.c index 49d90994aa2..394d0df7742 100644 --- a/regression/goto-analyzer/constant_propagation_01/main.c +++ b/regression/goto-analyzer/constant_propagation_01/main.c @@ -8,7 +8,6 @@ int main() { int x=1,y=2,z; z=x+y; - __CPROVER_assert(z==3, "z==3"); + __CPROVER_assert(z == 3, "z==3"); } - } diff --git a/regression/goto-analyzer/constant_propagation_02/main.c b/regression/goto-analyzer/constant_propagation_02/main.c index e6f6764badf..63c39f97d17 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++; } - __CPROVER_assert(j!=3, "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 3a929f776b8..dacc46b372c 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++; } - __CPROVER_assert(j==3, "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 b667e66dfe5..66290476992 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++; } - __CPROVER_assert(j==3, "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 7f5ae516853..3d947bbdd96 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++; } - __CPROVER_assert(j!=3, "j!=3"); + __CPROVER_assert(j != 3, "j!=3"); } diff --git a/regression/goto-analyzer/constant_propagation_06/main.c b/regression/goto-analyzer/constant_propagation_06/main.c index 4595085a85e..eb3234177c2 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++; } - __CPROVER_assert(i<51, "i<51"); + __CPROVER_assert(i < 51, "i<51"); } diff --git a/regression/goto-analyzer/constant_propagation_08/main.c b/regression/goto-analyzer/constant_propagation_08/main.c index fa70c7b001d..9bc63eda848 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; - __CPROVER_assert(a[0]==1 || a[1]==2, "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 e3ad2204ca2..8b004115196 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; - __CPROVER_assert(a[0]==0, "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 be7b386afad..dc79ad434ca 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; - __CPROVER_assert(a[0]==2, "a[0]==2"); + __CPROVER_assert(a[0] == 2, "a[0]==2"); return 0; } diff --git a/regression/goto-analyzer/constant_propagation_11/main.c b/regression/goto-analyzer/constant_propagation_11/main.c index 40e8b43d2e3..ed387e3b762 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; - __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_12/main.c b/regression/goto-analyzer/constant_propagation_12/main.c index e86aaba5d7b..c5f55fdda8a 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; - __CPROVER_assert(y==1, "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 393ebae92c9..377b9490213 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; - __CPROVER_assert(y==0, "y==0"); + __CPROVER_assert(y == 0, "y==0"); return 0; } diff --git a/regression/goto-analyzer/constant_propagation_14/main.c b/regression/goto-analyzer/constant_propagation_14/main.c index 7b38dd7be9e..34021bdd6aa 100644 --- a/regression/goto-analyzer/constant_propagation_14/main.c +++ b/regression/goto-analyzer/constant_propagation_14/main.c @@ -8,8 +8,8 @@ int main() else 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"); + __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_15/main.c b/regression/goto-analyzer/constant_propagation_15/main.c index 4e63b0f873a..b06e7a486de 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; - __CPROVER_assert(a[0]==2, "a[0]==2"); + __CPROVER_assert(a[0] == 2, "a[0]==2"); return 0; } diff --git a/regression/goto-analyzer/constant_propagation_17/main.c b/regression/goto-analyzer/constant_propagation_17/main.c index cb41fe9e87f..b080d5e33cc 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++; } - __CPROVER_assert(i<51, "i<51"); + __CPROVER_assert(i < 51, "i<51"); } diff --git a/regression/goto-analyzer/demo/main.c b/regression/goto-analyzer/demo/main.c index cbea87ebae9..57d32980518 100644 --- a/regression/goto-analyzer/demo/main.c +++ b/regression/goto-analyzer/demo/main.c @@ -1,6 +1,5 @@ #include - // To demonstrate run // $ goto-analyzer main.c --variable --verify --pointers --structs // Will show the asserts @@ -15,50 +14,49 @@ 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) + int i = 0, j = 2; + if(i == 0) { i++; j++; } // Knows we took if statement so can conclude assertion is true - __CPROVER_assert(j==3, "j==3"); // Verified + __CPROVER_assert(j == 3, "j==3"); // Verified - int value=4; + int value = 4; - int * p2v = &value; - int ** pp2v = &p2v; + int *p2v = &value; + int **pp2v = &p2v; - __CPROVER_assert(*p2v==4, "*p2v==4"); - __CPROVER_assert(**pp2v==4, "**pp2v==4"); + __CPROVER_assert(*p2v == 4, "*p2v==4"); + __CPROVER_assert(**pp2v == 4, "**pp2v==4"); - value=10; + value = 10; // Tracks the value pointed to has changed - __CPROVER_assert(*p2v==10, "*p2v==10"); - __CPROVER_assert(**pp2v==10, "**pp2v==10"); + __CPROVER_assert(*p2v == 10, "*p2v==10"); + __CPROVER_assert(**pp2v == 10, "**pp2v==10"); *p2v = 15; - __CPROVER_assert(value==15, "value==15"); - __CPROVER_assert(*p2v==15, "*p2v==15"); - __CPROVER_assert(**pp2v==15, "**pp2v==15"); + __CPROVER_assert(value == 15, "value==15"); + __CPROVER_assert(*p2v == 15, "*p2v==15"); + __CPROVER_assert(**pp2v == 15, "**pp2v==15"); **pp2v = 20; - __CPROVER_assert(value==20, "value==20"); - __CPROVER_assert(*p2v==20, "*p2v==20"); - __CPROVER_assert(**pp2v==20, "**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; - __CPROVER_assert(*p2v==5, "*p2v==5"); - __CPROVER_assert(**pp2v==5, "**pp2v==5"); + __CPROVER_assert(*p2v == 5, "*p2v==5"); + __CPROVER_assert(**pp2v == 5, "**pp2v==5"); if(unknown > 10) { @@ -69,20 +67,23 @@ void func(int unknown) p2v = &other; } - __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 + __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 int x = 4; - int * xp = &x; - int * yp = xp; + int *xp = &x; + int *yp = xp; - int ** ypp = &yp; + int **ypp = &yp; **ypp = *yp; - int array[4] = {0, 1 , 2, 3}; + int array[4] = {0, 1, 2, 3}; __CPROVER_assert(array[0] == 0, "array[0] == 0"); // Success __CPROVER_assert(array[3] == 3, "array[3] == 3"); // Success @@ -104,7 +105,6 @@ void func(int unknown) __CPROVER_assert(array[2] == 5, "array[2] == 5"); // Unknown __CPROVER_assert(array[3] == 3, "array[3] == 3"); // Success - typedef struct { int a; diff --git a/regression/goto-analyzer/intervals_01/main.c b/regression/goto-analyzer/intervals_01/main.c index 68f3c189bea..6481a350c00 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) - __CPROVER_assert(i>=10, "i>=10"); + __CPROVER_assert(i >= 10, "i>=10"); if(i>=10 && i<=20) - __CPROVER_assert(i!=30, "i!=30"); + __CPROVER_assert(i != 30, "i!=30"); if(i>=10 && i<=20) - __CPROVER_assert(i!=15, "i!=15"); // fails + __CPROVER_assert(i != 15, "i!=15"); // fails if(i<1 && i>10) __CPROVER_assert(0, "0"); if(i>=10 && j>=i) - __CPROVER_assert(j>=10, "j>=10"); + __CPROVER_assert(j >= 10, "j>=10"); if(i>=j) - __CPROVER_assert(i>=j, "i>=j"); // fails + __CPROVER_assert(i >= j, "i>=j"); // fails if(i>10) - __CPROVER_assert(i>=11, "i>=11"); + __CPROVER_assert(i >= 11, "i>=11"); if(i<=100 && j 0 && x < 20) { - __CPROVER_assert(x > -10 && x < 100, "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 6dc4da4fd02..af96021bfb5 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) - __CPROVER_assert(i>=1 && i<=2, "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 b1337e9f72c..9bd6851b160 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) - __CPROVER_assert(i>=1 || i<=2, "i>=1 || i<=2"); + __CPROVER_assert(i >= 1 || i <= 2, "i>=1 || i<=2"); return 0; } diff --git a/regression/goto-analyzer/intervals_08/main.c b/regression/goto-analyzer/intervals_08/main.c index 8c4b6683739..5dfe4a86efc 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) { - __CPROVER_assert(x < -10 && x < 100, "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 6dc4da4fd02..af96021bfb5 100644 --- a/regression/goto-analyzer/intervals_09/main.c +++ b/regression/goto-analyzer/intervals_09/main.c @@ -5,7 +5,7 @@ int main() if(i>0) if(i<3) - __CPROVER_assert(i>=1 && i<=2, "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 8eb55131936..b2a014bda2e 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, "j>100"); // 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,14 @@ int main() { /* Num, x values */ for (j = 0; j < Blen; j++) { y[i] = y[i] + B[j]*x_aux[j]; - __CPROVER_assert(y[i]>=-1.0f && y[i]<=1.0f, "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, "y[i]>=-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_13/main.c b/regression/goto-analyzer/intervals_13/main.c index 0de4b75dc1d..90b191c1dee 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) - __CPROVER_assert(i>=10, "i>=10"); // success + __CPROVER_assert(i >= 10, "i>=10"); // success if(i>=10 && i<=20) - __CPROVER_assert(i!=30, "i!=30"); // success + __CPROVER_assert(i != 30, "i!=30"); // success if(i>=10 && i<=20) - __CPROVER_assert(i!=15, "i!=15"); // fails + __CPROVER_assert(i != 15, "i!=15"); // fails if(i<1 && i>10) __CPROVER_assert(0, "0"); // success if(i>=10 && j>=i) - __CPROVER_assert(j>=10, "j>=10"); // success + __CPROVER_assert(j >= 10, "j>=10"); // success if(i>=j) - __CPROVER_assert(i>=j, "i>=j"); // unknown + __CPROVER_assert(i >= j, "i>=j"); // unknown if(i>10) - __CPROVER_assert(i>=11, "i>=11"); // success + __CPROVER_assert(i >= 11, "i>=11"); // success if(i<=100 && j2) + if(argc > 2) { - __CPROVER_assert(x.a==0, "x.a==0"); - __CPROVER_assert(x.a==1, "x.a==1"); - x.a=1; - __CPROVER_assert(x.a==0, "x.a==0"); - __CPROVER_assert(x.a==1, "x.a==1"); + __CPROVER_assert(x.a == 0, "x.a==0"); + __CPROVER_assert(x.a == 1, "x.a==1"); + x.a = 1; + __CPROVER_assert(x.a == 0, "x.a==0"); + __CPROVER_assert(x.a == 1, "x.a==1"); } - __CPROVER_assert(x.a==0, "x.a==0"); - __CPROVER_assert(x.a==1, "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/sensitivity-function-call-array/main.c b/regression/goto-analyzer/sensitivity-function-call-array/main.c index 4137d35003a..e6a99068a53 100644 --- a/regression/goto-analyzer/sensitivity-function-call-array/main.c +++ b/regression/goto-analyzer/sensitivity-function-call-array/main.c @@ -9,23 +9,23 @@ int main(int argc, char *argv[]) int *p2arr = arr_x; p2arr = bar(arr_x, arr_y); - assert(*arr_y==2); + assert(*arr_y == 2); // assert(arr_y[1]==3); - assert(p2arr==arr_y); - assert(*p2arr==2); + assert(p2arr == arr_y); + assert(*p2arr == 2); // assert(p2arr[1]==3); } int *bar(int *arr_unmodified, int *arr_modified) { - assert(*arr_unmodified==1); + assert(*arr_unmodified == 1); // assert(arr_unmodified[1]==2); (*arr_modified) += 1; // arr_modified[1] = 3; - assert(*arr_modified==2); + assert(*arr_modified == 2); // assert(arr_modified[1]==3); return arr_modified; diff --git a/regression/goto-analyzer/sensitivity-function-call-opaque/main.c b/regression/goto-analyzer/sensitivity-function-call-opaque/main.c index 7a370b56c4b..f7fb09c85eb 100644 --- a/regression/goto-analyzer/sensitivity-function-call-opaque/main.c +++ b/regression/goto-analyzer/sensitivity-function-call-opaque/main.c @@ -2,21 +2,23 @@ int global_value; -int opaque(int other, int* side_effect); +int opaque(int other, int *side_effect); int main(int argc, char *argv[]) { - int x=3; - int y=4; + int x = 3; + int y = 4; - global_value=4; + global_value = 4; - int z=bar(x+1, &y); + int z = bar(x + 1, &y); - assert(x==3); // Success - assert(y==4); // Unknown - the opaque function could have modified it - assert(z==0); // Unknown - the opaque function could have returned anything - assert(global_value==4); // Unknown - the opaque function could have modified this + assert(x == 3); // Success + assert(y == 4); // Unknown - the opaque function could have modified it + assert(z == 0); // Unknown - the opaque function could have returned anything + assert( + global_value == + 4); // Unknown - the opaque function could have modified this return 0; } diff --git a/regression/goto-analyzer/sensitivity-function-call-pointer/main.c b/regression/goto-analyzer/sensitivity-function-call-pointer/main.c index 246e40b4100..8b58f431931 100644 --- a/regression/goto-analyzer/sensitivity-function-call-pointer/main.c +++ b/regression/goto-analyzer/sensitivity-function-call-pointer/main.c @@ -4,22 +4,22 @@ int *bar(int *unmodified, int *modifed); int main(int argc, char *argv[]) { - int x=3; - int y=4; - int *p2x=&x; + int x = 3; + int y = 4; + int *p2x = &x; p2x = bar(&x, &y); - assert(y==5); - assert(p2x==&y); - assert(*p2x==5); + assert(y == 5); + assert(p2x == &y); + assert(*p2x == 5); } int *bar(int *unmodified, int *modifed) { - assert(*unmodified==3); + assert(*unmodified == 3); (*modifed) += 1; - assert(*modifed==5); + assert(*modifed == 5); return modifed; } diff --git a/regression/goto-analyzer/sensitivity-function-call-primitive/main.c b/regression/goto-analyzer/sensitivity-function-call-primitive/main.c index c9afbfc927d..1c7a50e0983 100644 --- a/regression/goto-analyzer/sensitivity-function-call-primitive/main.c +++ b/regression/goto-analyzer/sensitivity-function-call-primitive/main.c @@ -2,13 +2,13 @@ int bar(int other) { - assert(other==4); + assert(other == 4); return other + 1; } int main(int argc, char *argv[]) { - int x=3; - int y=bar(x+1); - assert(y==5); + int x = 3; + int y = bar(x + 1); + assert(y == 5); } diff --git a/regression/goto-analyzer/sensitivity-function-call-varargs/main.c b/regression/goto-analyzer/sensitivity-function-call-varargs/main.c index 1f35e93715f..920ff4ab43d 100644 --- a/regression/goto-analyzer/sensitivity-function-call-varargs/main.c +++ b/regression/goto-analyzer/sensitivity-function-call-varargs/main.c @@ -3,13 +3,13 @@ int bar(int size, ...) { - int total=0; + int total = 0; va_list args; va_start(args, size); for(int i = 0; i < size; ++i) { int val = va_arg(args, int); - total+=val; + total += val; } va_end(args); @@ -18,9 +18,9 @@ int bar(int size, ...) int main(int argc, char *argv[]) { - int y=bar(4, 1, 2, 2, 1); - assert(y==6); + int y = bar(4, 1, 2, 2, 1); + assert(y == 6); - int z=bar(0); - assert(z==0); + int z = bar(0); + assert(z == 0); } diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/sensitivity_dependency_arrays.c b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/sensitivity_dependency_arrays.c index 6fa4d476ef4..8c28a4a1b2f 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/sensitivity_dependency_arrays.c +++ b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/sensitivity_dependency_arrays.c @@ -7,41 +7,41 @@ void do_arrays() int x[2]; // Simple variables. - x[0]=10; - x[1]=20; - x[0]=30; - x[1]=40; - x[1]=x[0]; - x[0]=x[1]; - x[0]=5; - x[0]=x[0]+10; - x[1]=10; + x[0] = 10; + x[1] = 20; + x[0] = 30; + x[1] = 40; + x[1] = x[0]; + x[0] = x[1]; + x[0] = 5; + x[0] = x[0] + 10; + x[1] = 10; if(bool_) { - x[0]=20; + x[0] = 20; } else { - x[0]=20; + x[0] = 20; } - x[0]=0; + x[0] = 0; if(bool_1) { - x[0]=3; + x[0] = 3; if(bool_2) { - x[0]=5; + x[0] = 5; } } else { - x[0]=7; + x[0] = 7; } - x[1]=10; - x[0]=20; + x[1] = 10; + x[0] = 20; } int main() diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/sensitivity_dependency_pointers.c b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/sensitivity_dependency_pointers.c index 1c3851d5eb7..84e1366830f 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/sensitivity_dependency_pointers.c +++ b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/sensitivity_dependency_pointers.c @@ -4,24 +4,24 @@ void do_pointers() int bool_1; int bool_2; - int x=10; + int x = 10; int *x_p; - int y=20; + int y = 20; int *y_p; - x_p=&x; + x_p = &x; - *x_p=30; - x=40; + *x_p = 30; + x = 40; - *x_p=*y_p; - x=50; - y_p=&x; + *x_p = *y_p; + x = 50; + y_p = &x; - *x_p=60; + *x_p = 60; - int j=*y_p; + int j = *y_p; } int main() diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-structs/sensitivity_dependency_structs.c b/regression/goto-analyzer/sensitivity-last-written-locations-structs/sensitivity_dependency_structs.c index 56ae53c041a..5bfc8ce6eea 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-structs/sensitivity_dependency_structs.c +++ b/regression/goto-analyzer/sensitivity-last-written-locations-structs/sensitivity_dependency_structs.c @@ -1,4 +1,5 @@ -struct Ages { +struct Ages +{ int x; int y; }; @@ -12,49 +13,48 @@ void do_structs() struct Ages st; // Simple variables. - st.x=10; - st.y=20; - st.x=30; - st.y=40; - st.y=st.x; - st.x=st.y; - st.x=5; - st.x=st.x+10; - st.y=10; + st.x = 10; + st.y = 20; + st.x = 30; + st.y = 40; + st.y = st.x; + st.x = st.y; + st.x = 5; + st.x = st.x + 10; + st.y = 10; if(bool_) { - st.x=20; + st.x = 20; } else { - st.x=20; + st.x = 20; } - st.x=0; + st.x = 0; if(bool_1) { - st.x=3; + st.x = 3; if(bool_2) { - st.x=5; + st.x = 5; } } else { - st.x=7; + st.x = 7; } - st.y=10; - st.x=20; + st.y = 10; + st.x = 20; struct Ages new_age; - new_age=st; + new_age = st; } int main() { do_structs(); } - diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-variables/sensitivity_dependency_variables.c b/regression/goto-analyzer/sensitivity-last-written-locations-variables/sensitivity_dependency_variables.c index a0551df37fc..1860fcfee45 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-variables/sensitivity_dependency_variables.c +++ b/regression/goto-analyzer/sensitivity-last-written-locations-variables/sensitivity_dependency_variables.c @@ -6,55 +6,55 @@ void do_variables() int bool_1; int bool_2; - global_x=5; + global_x = 5; // Simple variables. - int x=10; - int y=20; - x=30; - y=40; - y=x; - x=y; - x=5; - x=x+10; - y=10; + int x = 10; + int y = 20; + x = 30; + y = 40; + y = x; + x = y; + x = 5; + x = x + 10; + y = 10; if(bool_) { - x=20; + x = 20; } else { - x=20; + x = 20; } - x=50; + x = 50; if(bool_) { - x=20; + x = 20; } else { - x=30; + x = 30; } - x=0; + x = 0; if(bool_1) { - x=3; + x = 3; if(bool_2) { - x=5; + x = 5; } } else { - x=7; + x = 7; } - y=10; - x=20; + y = 10; + x = 20; } int main() 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 0ea6f6ac258..d5ca7bccd16 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 - __CPROVER_assert(a[1][2]==0, "a[1][2]==0"); - __CPROVER_assert(a[1][2]==1, "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 - __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"); // Test alternative syntax for accessing an array value - __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"); + __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; } - __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"); + __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; } - __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"); + __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 - __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"); + __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 - __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"); + __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 - __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"); + __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 - __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"); + __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 - __CPROVER_assert(a[100][0]==0, "a[100][0]==0"); - __CPROVER_assert(a[0][100]==0, "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; - __CPROVER_assert(c==0, "c==0"); + __CPROVER_assert(c == 0, "c==0"); c=0; a[0][100]=1; - __CPROVER_assert(c==0, "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; - __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"); + __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; - __CPROVER_assert(ej[0][1]==0, "ej[0][1]==0"); - __CPROVER_assert(ej[2][1]==0, "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; - __CPROVER_assert(ek[0][1]==0, "ek[0][1]==0"); - __CPROVER_assert(c==0, "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 f90bc5e2f0b..a7a2ec49825 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 - __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"); + __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 - __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"); + __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 - __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"); + __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 - __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"); + __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 - __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"); + __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 - __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"); + __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 - __CPROVER_assert(a[100]==&a2, "a[100]==&a2"); - __CPROVER_assert(*a[100]==2, "*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; - __CPROVER_assert(b[1]==&b1, "b[1]==&b1"); - __CPROVER_assert(*b[1]==11, "*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; - __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"); + __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; - __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"); + __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; - __CPROVER_assert(ek[0]==&ek0, "ek[0]==&ek0"); - __CPROVER_assert(*ek[0]==60, "*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; @@ -159,18 +159,18 @@ int main(int argc, char *argv[]) int i; if(argc > 2) { - i=0; + i = 0; } else { - i=1; + i = 1; } - *(ps[i])=4; + *(ps[i]) = 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"); + __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 b0b413b7014..eec18d869ff 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 - __CPROVER_assert(a[1]==0, "a[1]==0"); - __CPROVER_assert(a[1]==1, "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 - __CPROVER_assert(b[1]==0, "b[1]==0"); - __CPROVER_assert(b[1]==1, "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 - __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"); + __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 - __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"); + __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 - __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"); + __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 - __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"); + __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 - __CPROVER_assert(a[100]==0, "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; - __CPROVER_assert(b[1]==0, "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; - __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"); + __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; - __CPROVER_assert(ej[0]==0, "ej[0]==0"); - __CPROVER_assert(ej[2]==0, "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; - __CPROVER_assert(ek[0]==0, "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 c56bc05e551..19c8cbf6eb7 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'; - __CPROVER_assert(x=='a', "x=='a'"); - __CPROVER_assert(x=='b', "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 f45b9db843f..a4bb5450655 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; - __CPROVER_assert(x==0.0, "x==0.0"); - __CPROVER_assert(x==1.0, "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 13845600396..8d7215ded25 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; } - __CPROVER_assert(x==0, "x==0"); - __CPROVER_assert(x==1, "x==1"); - __CPROVER_assert(x==y, "x==y"); + __CPROVER_assert(x == 0, "x==0"); + __CPROVER_assert(x == 1, "x==1"); + __CPROVER_assert(x == y, "x==y"); - __CPROVER_assert(x<1, "x<1"); - __CPROVER_assert(x<-1, "x<-1"); - __CPROVER_assert(x-1, "x>-1"); - __CPROVER_assert(x>1, "x>1"); - __CPROVER_assert(x>y, "x>y"); + __CPROVER_assert(x > -1, "x>-1"); + __CPROVER_assert(x > 1, "x>1"); + __CPROVER_assert(x > y, "x>y"); - __CPROVER_assert(x!=1, "x!=1"); - __CPROVER_assert(x!=0, "x!=0"); - __CPROVER_assert(x!=y, "x!=y"); + __CPROVER_assert(x != 1, "x!=1"); + __CPROVER_assert(x != 0, "x!=0"); + __CPROVER_assert(x != y, "x!=y"); - __CPROVER_assert(!(x==1), "!(x==1)"); - __CPROVER_assert(!(x==0), "!(x==0)"); - __CPROVER_assert(!(x==y), "!(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 - __CPROVER_assert(y<2, "y<2"); - __CPROVER_assert(y>2, "y>2"); - __CPROVER_assert(y==1, "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; - __CPROVER_assert(z==0, "z==0"); - __CPROVER_assert(z==10, "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) { - __CPROVER_assert(x==0, "x==0"); - __CPROVER_assert(x==1, "x==1"); - __CPROVER_assert(y==0, "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 - __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"); + __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 5e6f1f1da73..5a0fa9a1475 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; - __CPROVER_assert(x==&a, "x==&a"); - __CPROVER_assert(x==&b, "x==&b"); - __CPROVER_assert(x==x2, "x==x2"); - __CPROVER_assert(x==y, "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 - __CPROVER_assert(*x==0, "*x==0"); - __CPROVER_assert(*x==1, "*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; - __CPROVER_assert(*x==1, "*x==1"); - __CPROVER_assert(*x==0, "*x==0"); + __CPROVER_assert(*x == 1, "*x==1"); + __CPROVER_assert(*x == 0, "*x==0"); // Writing to a dereferenced pointer *x=2; - __CPROVER_assert(a==2, "a==2"); - __CPROVER_assert(a==0, "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; } - __CPROVER_assert(x==&a, "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; } - __CPROVER_assert(*x==0, "*x==0"); - __CPROVER_assert(x==&a, "x==&a"); - __CPROVER_assert(x==&b, "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 e3aebf81673..4ae885d4a95 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,40 +6,40 @@ int main(int argc, char *argv[]) // Test reading from an array using a pointer int a[3]={1, 2, 3}; int *p=a; - __CPROVER_assert(p==&a[0], "p==&a[0]"); + __CPROVER_assert(p == &a[0], "p==&a[0]"); // Read through pointer - __CPROVER_assert(*p==1, "*p==1"); + __CPROVER_assert(*p == 1, "*p==1"); // Read through offset pointer - __CPROVER_assert(p[1]==2, "p[1]==2"); - __CPROVER_assert(1[p]==2, "1[p]==2"); + __CPROVER_assert(p[1] == 2, "p[1]==2"); + __CPROVER_assert(1 [p] == 2, "1[p]==2"); - __CPROVER_assert(*(p+1)==2, "*(p+1)==2"); - __CPROVER_assert(*(1+p)==2, "*(1+p)==2"); + __CPROVER_assert(*(p + 1) == 2, "*(p+1)==2"); + __CPROVER_assert(*(1 + p) == 2, "*(1+p)==2"); // Test pointer arithmetic int *q=&a[1]; - __CPROVER_assert(q==p+1, "q==p+1"); - __CPROVER_assert(*q==2, "*q==2"); - __CPROVER_assert(*(q-1)==1, "*(q-1)==1"); + __CPROVER_assert(q == p + 1, "q==p+1"); + __CPROVER_assert(*q == 2, "*q==2"); + __CPROVER_assert(*(q - 1) == 1, "*(q-1)==1"); // Test pointer diffs ptrdiff_t x=1; - __CPROVER_assert(q-p==x, "q-p==x"); + __CPROVER_assert(q - p == x, "q-p==x"); // Test writing into an array using a pointer *q=4; - __CPROVER_assert(a[1]==4, "a[1]==4"); + __CPROVER_assert(a[1] == 4, "a[1]==4"); - p[1]=5; - __CPROVER_assert(a[1]==5, "a[1]==5"); + p[1] = 5; + __CPROVER_assert(a[1] == 5, "a[1]==5"); - *(p+1)=6; - __CPROVER_assert(a[1]==6, "a[1]==6"); + *(p + 1) = 6; + __CPROVER_assert(a[1] == 6, "a[1]==6"); - *(1+p)=7; - __CPROVER_assert(a[1]==7, "a[1]==7"); + *(1 + p) = 7; + __CPROVER_assert(a[1] == 7, "a[1]==7"); a[1]=2; @@ -57,23 +57,23 @@ int main(int argc, char *argv[]) // Test reading from an array using a pointer with more than one possible // value - __CPROVER_assert(*r==2, "*r==2"); - __CPROVER_assert(*r==1, "*r==1"); - __CPROVER_assert(*s==0, "*s==0"); - __CPROVER_assert(*s==1, "*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]; - __CPROVER_assert(t==p+i, "t==p+i"); + __CPROVER_assert(t == p + i, "t==p+i"); // Test pointer diffs with an unknown index ptrdiff_t y=i; - __CPROVER_assert(t-p==y, "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; - __CPROVER_assert(a[i]==5, "a[i]==5"); - __CPROVER_assert(a[1]==5, "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 61aa658a2ec..6ea079e21e1 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 - __CPROVER_assert(**x==0, "**x==0"); - __CPROVER_assert(**x==1, "**x==1"); + __CPROVER_assert(**x == 0, "**x==0"); + __CPROVER_assert(**x == 1, "**x==1"); a=1; - __CPROVER_assert(**x==1, "**x==1"); - __CPROVER_assert(**x==0, "**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; - __CPROVER_assert(a==2, "a==2"); - __CPROVER_assert(a==1, "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 1b741048d1a..b0cfc99e040 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,42 +12,42 @@ int main(int argc, char *argv[]) x.a=0; x.b=1.0; struct int_float *p=&x; - __CPROVER_assert((*p).a==0, "(*p).a==0"); - __CPROVER_assert((*p).a==1, "(*p).a==1"); + __CPROVER_assert((*p).a == 0, "(*p).a==0"); + __CPROVER_assert((*p).a == 1, "(*p).a==1"); // Test alternative syntax - __CPROVER_assert(p->a==0, "p->a==0"); - __CPROVER_assert(p->a==1, "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; - __CPROVER_assert(p->b==2.0, "p->b==2.0"); - __CPROVER_assert(p->b==1.0, "p->b==1.0"); + __CPROVER_assert(p->b == 2.0, "p->b==2.0"); + __CPROVER_assert(p->b == 1.0, "p->b==1.0"); // pointers to components - int * comp_p = &x.a; - __CPROVER_assert(comp_p==&x.a, "comp_p==&x.a"); - __CPROVER_assert(comp_p==&x.b, "comp_p==&x.b"); - __CPROVER_assert(*comp_p==0, "*comp_p==0"); - __CPROVER_assert(*comp_p==1, "*comp_p==1"); - - float * compb_p = &x.b; - __CPROVER_assert(compb_p==&x.a, "compb_p==&x.a"); - __CPROVER_assert(compb_p==&x.b, "compb_p==&x.b"); - __CPROVER_assert(*compb_p==2.0, "*compb_p==2.0"); - __CPROVER_assert(*compb_p==1.0, "*compb_p==1.0"); + int *comp_p = &x.a; + __CPROVER_assert(comp_p == &x.a, "comp_p==&x.a"); + __CPROVER_assert(comp_p == &x.b, "comp_p==&x.b"); + __CPROVER_assert(*comp_p == 0, "*comp_p==0"); + __CPROVER_assert(*comp_p == 1, "*comp_p==1"); + + float *compb_p = &x.b; + __CPROVER_assert(compb_p == &x.a, "compb_p==&x.a"); + __CPROVER_assert(compb_p == &x.b, "compb_p==&x.b"); + __CPROVER_assert(*compb_p == 2.0, "*compb_p==2.0"); + __CPROVER_assert(*compb_p == 1.0, "*compb_p==1.0"); // Use pointer implicitly pointing at the first component - int * implicit_p = &x; - __CPROVER_assert(implicit_p==&x.a, "implicit_p==&x.a"); - __CPROVER_assert(implicit_p==&x, "implicit_p==&x"); - __CPROVER_assert(*implicit_p==0, "*implicit_p==0"); - __CPROVER_assert(*implicit_p==1, "*implicit_p==1"); + int *implicit_p = &x; + __CPROVER_assert(implicit_p == &x.a, "implicit_p==&x.a"); + __CPROVER_assert(implicit_p == &x, "implicit_p==&x"); + __CPROVER_assert(*implicit_p == 0, "*implicit_p==0"); + __CPROVER_assert(*implicit_p == 1, "*implicit_p==1"); // Write through pointer implicitly pointing at the first component - *implicit_p=5; - __CPROVER_assert(x.a==5, "x.a==5"); - __CPROVER_assert(x.a==1, "x.a==1"); + *implicit_p = 5; + __CPROVER_assert(x.a == 5, "x.a==5"); + __CPROVER_assert(x.a == 1, "x.a==1"); 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 646aa133183..c68fb8837a4 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; - __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"); + __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; } - __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"); + __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; } - __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"); + __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; } - __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"); + __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 19371f81644..dbc196c7f35 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; - __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"); + __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; } - __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"); + __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; } - __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"); + __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; } - __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"); + __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 dcaa72c4f34..85f1cc1afc7 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; - __CPROVER_assert(x.s1.a==0, "x.s1.a==0"); - __CPROVER_assert(x.s2.b==3.0f, "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; } - __CPROVER_assert(x.s1.a==0, "x.s1.a==0"); - __CPROVER_assert(x.s1.a==10, "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; } - __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"); + __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; } - __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"); + __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 1d54f561265..2804a4805a2 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; - __CPROVER_assert(x.a==0, "x.a==0"); - __CPROVER_assert(x.a==1, "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; } - __CPROVER_assert(x.a==0, "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; } - __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"); + __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; } - __CPROVER_assert(x.a<2, "x.a<2"); - __CPROVER_assert(x.a>2, "x.a>2"); - __CPROVER_assert(x.a==1, "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-loop/main.c b/regression/goto-analyzer/sensitivity-test-constants-array-loop/main.c index 58248b83ae3..f9ac19c71b1 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array-loop/main.c +++ b/regression/goto-analyzer/sensitivity-test-constants-array-loop/main.c @@ -2,12 +2,11 @@ static int array[2]; void main(void) { + int i; - int i; + for(i = 0; i < 1; i++) + array[i] = 5; - for (i=0; i < 1; i++) - array[i] = 5; - - __CPROVER_assert(array[0] == 5, "array[0] == 5"); - __CPROVER_assert(array[1] == 5, "array[1] == 5"); + __CPROVER_assert(array[0] == 5, "array[0] == 5"); + __CPROVER_assert(array[1] == 5, "array[1] == 5"); } diff --git a/regression/goto-analyzer/sensitivity-test-data-dependency-context/data-dependency-context.c b/regression/goto-analyzer/sensitivity-test-data-dependency-context/data-dependency-context.c index 80b466c1c03..de388175719 100644 --- a/regression/goto-analyzer/sensitivity-test-data-dependency-context/data-dependency-context.c +++ b/regression/goto-analyzer/sensitivity-test-data-dependency-context/data-dependency-context.c @@ -1,4 +1,5 @@ -struct structt { +struct structt +{ int a; int b; }; @@ -13,20 +14,20 @@ int out1, out2, out3; void main(void) { int i; - if (in == 1) + if(in == 1) st.a++; - if (in == 2) + if(in == 2) st.b++; out1 = st.a; out2 = st.b; out3 = st.a + st.b; - if (in == 1) + if(in == 1) ar[0]++; - if (in == 2) + if(in == 2) ar[1]++; out1 = ar[0]; @@ -37,7 +38,7 @@ void main(void) arr[1] = 2; arr[2] = 3; - if (in > 0) + if(in > 0) { arr[2] = arr[1]; } diff --git a/regression/goto-analyzer/sensitivity-test-struct-initialization/struct-initialization.c b/regression/goto-analyzer/sensitivity-test-struct-initialization/struct-initialization.c index 1cfa00ad9c2..0e31047a7eb 100644 --- a/regression/goto-analyzer/sensitivity-test-struct-initialization/struct-initialization.c +++ b/regression/goto-analyzer/sensitivity-test-struct-initialization/struct-initialization.c @@ -1,53 +1,54 @@ -struct lexigraphically_ordered_struct { +struct lexigraphically_ordered_struct +{ int a; int b; }; -struct lexigraphically_unordered_struct { +struct lexigraphically_unordered_struct +{ int b; int a; }; struct lexigraphically_ordered_struct los; -struct lexigraphically_ordered_struct los2 = {.a=3, .b=4}; -struct lexigraphically_ordered_struct los3 = {.b=4, .a=3}; -struct lexigraphically_ordered_struct los4 = {.a=3}; -struct lexigraphically_ordered_struct los5 = {.b=4}; +struct lexigraphically_ordered_struct los2 = {.a = 3, .b = 4}; +struct lexigraphically_ordered_struct los3 = {.b = 4, .a = 3}; +struct lexigraphically_ordered_struct los4 = {.a = 3}; +struct lexigraphically_ordered_struct los5 = {.b = 4}; struct lexigraphically_ordered_struct los6 = {3, 4}; struct lexigraphically_unordered_struct lus; -struct lexigraphically_unordered_struct lus2 = {.a=3, .b=4}; -struct lexigraphically_unordered_struct lus3 = {.b=4, .a=3}; -struct lexigraphically_unordered_struct lus4 = {.a=3}; -struct lexigraphically_unordered_struct lus5 = {.b=4}; +struct lexigraphically_unordered_struct lus2 = {.a = 3, .b = 4}; +struct lexigraphically_unordered_struct lus3 = {.b = 4, .a = 3}; +struct lexigraphically_unordered_struct lus4 = {.a = 3}; +struct lexigraphically_unordered_struct lus5 = {.b = 4}; struct lexigraphically_unordered_struct lus6 = {4, 3}; void main(void) { - __CPROVER_assert(los.a==0, "los.a==0"); - __CPROVER_assert(los.b==0, "los.b==0"); - __CPROVER_assert(los2.a==3, "los2.a==3"); - __CPROVER_assert(los2.b==4, "los2.b==4"); - __CPROVER_assert(los3.a==3, "los3.a==3"); - __CPROVER_assert(los3.b==4, "los3.b==4"); - __CPROVER_assert(los4.a==3, "los4.a==3"); - __CPROVER_assert(los4.b==0, "los4.b==0"); - __CPROVER_assert(los5.a==0, "los5.a==0"); - __CPROVER_assert(los5.b==4, "los5.b==4"); - __CPROVER_assert(los6.a==3, "los6.a==3"); - __CPROVER_assert(los6.b==4, "los6.b==4"); + __CPROVER_assert(los.a == 0, "los.a==0"); + __CPROVER_assert(los.b == 0, "los.b==0"); + __CPROVER_assert(los2.a == 3, "los2.a==3"); + __CPROVER_assert(los2.b == 4, "los2.b==4"); + __CPROVER_assert(los3.a == 3, "los3.a==3"); + __CPROVER_assert(los3.b == 4, "los3.b==4"); + __CPROVER_assert(los4.a == 3, "los4.a==3"); + __CPROVER_assert(los4.b == 0, "los4.b==0"); + __CPROVER_assert(los5.a == 0, "los5.a==0"); + __CPROVER_assert(los5.b == 4, "los5.b==4"); + __CPROVER_assert(los6.a == 3, "los6.a==3"); + __CPROVER_assert(los6.b == 4, "los6.b==4"); - __CPROVER_assert(lus.a==0, "lus.a==0"); - __CPROVER_assert(lus.b==0, "lus.b==0"); - __CPROVER_assert(lus2.a==3, "lus2.a==3"); - __CPROVER_assert(lus2.b==4, "lus2.b==4"); - __CPROVER_assert(lus3.a==3, "lus3.a==3"); - __CPROVER_assert(lus3.b==4, "lus3.b==4"); - __CPROVER_assert(lus4.a==3, "lus4.a==3"); - __CPROVER_assert(lus4.b==0, "lus4.b==0"); - __CPROVER_assert(lus5.a==0, "lus5.a==0"); - __CPROVER_assert(lus5.b==4, "lus5.b==4"); - __CPROVER_assert(lus6.a==3, "lus6.a==3"); - __CPROVER_assert(lus6.b==4, "lus6.b==4"); + __CPROVER_assert(lus.a == 0, "lus.a==0"); + __CPROVER_assert(lus.b == 0, "lus.b==0"); + __CPROVER_assert(lus2.a == 3, "lus2.a==3"); + __CPROVER_assert(lus2.b == 4, "lus2.b==4"); + __CPROVER_assert(lus3.a == 3, "lus3.a==3"); + __CPROVER_assert(lus3.b == 4, "lus3.b==4"); + __CPROVER_assert(lus4.a == 3, "lus4.a==3"); + __CPROVER_assert(lus4.b == 0, "lus4.b==0"); + __CPROVER_assert(lus5.a == 0, "lus5.a==0"); + __CPROVER_assert(lus5.b == 4, "lus5.b==4"); + __CPROVER_assert(lus6.a == 3, "lus6.a==3"); + __CPROVER_assert(lus6.b == 4, "lus6.b==4"); } - diff --git a/regression/goto-analyzer/unreachable_assertions_01/main.c b/regression/goto-analyzer/unreachable_assertions_01/main.c index d89733963f7..35979cef8ce 100644 --- a/regression/goto-analyzer/unreachable_assertions_01/main.c +++ b/regression/goto-analyzer/unreachable_assertions_01/main.c @@ -1,28 +1,32 @@ #include -int nondet_int (void); +int nondet_int(void); -int main (int argc, char **argv) +int main(int argc, char **argv) { int a = 1; int b = 2; int x = nondet_int(); int y = nondet_int(); - if (a == b) - __CPROVER_assert(0, "0"); // Trivial false + if(a == b) + __CPROVER_assert(0, "0"); // Trivial false - if (a == b) - __CPROVER_assert(1, "1"); // Trivial true + if(a == b) + __CPROVER_assert(1, "1"); // Trivial true - if (a == b) + if(a == b) __CPROVER_assert(x == y, "x == y"); // Undetermined - if (a == b) - __CPROVER_assert(!(x == y) || (x + 1 + a == b + y), "!(x == y) || (x + 1 + a == b + y)"); // Non-trivial true + if(a == b) + __CPROVER_assert( + !(x == y) || (x + 1 + a == b + y), + "!(x == y) || (x + 1 + a == b + y)"); // Non-trivial true - if (a == b) - __CPROVER_assert(!(!(x == y) || (x + 1 + a == b + y)), "!(!(x == y) || (x + 1 + a == b + y)"); // Non-trivial false + if(a == b) + __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/variable-sensitivity-annihiliator-test/main.c b/regression/goto-analyzer/variable-sensitivity-annihiliator-test/main.c index 7881ba7ff30..ca69ea73386 100644 --- a/regression/goto-analyzer/variable-sensitivity-annihiliator-test/main.c +++ b/regression/goto-analyzer/variable-sensitivity-annihiliator-test/main.c @@ -14,12 +14,12 @@ void main(void) void func(void) { - if (g_in1 == 0) - g_out = 1; // unreachable. + if(g_in1 == 0) + g_out = 1; // unreachable. - if (g_in2 == 0) + if(g_in2 == 0) g_out = 2; - if (g_in1 == 0 && g_in2 == 0) - g_out = 3; // unreachable, but not . + if(g_in1 == 0 && g_in2 == 0) + g_out = 3; // unreachable, but not . } diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c index 553697b1b07..4f0b403fe4f 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/main.c @@ -1,27 +1,27 @@ void param_test_val(int array[], int x) { - array[1] = x; + array[1] = x; } void pass_param() { - int b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - param_test_val(b, 5); + param_test_val(b, 5); - // This assertion should be true since b[0] is unmodified - __CPROVER_assert(b[0]==0, "b[0]==0"); + // This assertion should be true since b[0] is unmodified + __CPROVER_assert(b[0] == 0, "b[0]==0"); - // This assertion should be true since b[1] can only have one value - __CPROVER_assert(b[1]==5, "b[1]==5"); + // This assertion should be true since b[1] can only have one value + __CPROVER_assert(b[1] == 5, "b[1]==5"); - param_test_val(b, 6); + param_test_val(b, 6); - // Both these assertions shoul be unknown since the domain for - // param_test_val, x is TOP so we don't know what is written - __CPROVER_assert(b[1]==5, "b[1]==5"); - __CPROVER_assert(b[1]==6, "b[1]==6"); + // Both these assertions shoul be unknown since the domain for + // param_test_val, x is TOP so we don't know what is written + __CPROVER_assert(b[1] == 5, "b[1]==5"); + __CPROVER_assert(b[1] == 6, "b[1]==6"); - // b[0] is still not modified so this assertion should still be true - __CPROVER_assert(b[0]==0, "b[0]==0"); + // b[0] is still not modified so this assertion should still be true + __CPROVER_assert(b[0] == 0, "b[0]==0"); } \ No newline at end of file diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/main.c index da3e308c69f..993f0ee5ace 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/main.c @@ -1,26 +1,27 @@ -void param_function(int *old_val, int new_val) +void param_function(int *old_val, int new_val) { - *old_val = new_val; + *old_val = new_val; } -void param_function_extra(int *old_val, int new_val) +void param_function_extra(int *old_val, int new_val) { - *old_val = new_val; + *old_val = new_val; } void test_param_function(int nondet) { - int a = 5; - int b; - __CPROVER_assert(a==5, "a==5"); - if (nondet) { - a = 6; - b = 7; - goto whatever; - } - param_function(&a, 10); - param_function_extra(&b, 7); + int a = 5; + int b; + __CPROVER_assert(a == 5, "a==5"); + if(nondet) + { + a = 6; + b = 7; + goto whatever; + } + param_function(&a, 10); + param_function_extra(&b, 7); whatever: - __CPROVER_assert(a==10, "a==10"); - __CPROVER_assert(b==7, "b==7"); + __CPROVER_assert(a == 10, "a==10"); + __CPROVER_assert(b == 7, "b==7"); } \ No newline at end of file diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/main.c index b2c9858f8f2..589d00a5582 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/main.c @@ -1,32 +1,32 @@ int non_terminating(int *a, int val) { - while (1) - { - a = val; - } - return a; + while(1) + { + a = val; + } + return a; } int non_terminating_extra(int *a, int val) { - while (1) - { - a = val; - } - return a; + while(1) + { + a = val; + } + return a; } void test_non_terminating() { - int one_val = 5; - int second_val = 6; - __CPROVER_assert(one_val==5, "one_val==5"); - __CPROVER_assert(second_val==6, "second_val==6"); + int one_val = 5; + int second_val = 6; + __CPROVER_assert(one_val == 5, "one_val==5"); + __CPROVER_assert(second_val == 6, "second_val==6"); - non_terminating(&one_val, 10); - __CPROVER_assert(one_val==10, "one_val==10"); - non_terminating_extra(&second_val, 12); - __CPROVER_assert(second_val==12, "second_val==12"); - non_terminating_extra(&second_val, 13); - __CPROVER_assert(second_val==13, "second_val==13"); + non_terminating(&one_val, 10); + __CPROVER_assert(one_val == 10, "one_val==10"); + non_terminating_extra(&second_val, 12); + __CPROVER_assert(second_val == 12, "second_val==12"); + non_terminating_extra(&second_val, 13); + __CPROVER_assert(second_val == 13, "second_val==13"); } \ No newline at end of file diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c index eaddbedf304..d5f1909a364 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/main.c @@ -7,9 +7,9 @@ void simple_function(void) int j = 0; } -void pointer_function(int * write_to, int value) +void pointer_function(int *write_to, int value) { - *write_to=value; + *write_to = value; } void modify_global_function(int new_val) @@ -22,14 +22,14 @@ void simple_test() int i = 0; global = 0; simple_function(); - __CPROVER_assert(i==0, "i==0"); - __CPROVER_assert(global==0, "global==0"); + __CPROVER_assert(i == 0, "i==0"); + __CPROVER_assert(global == 0, "global==0"); i = 1; global = 2; simple_function(); - __CPROVER_assert(i==1, "i==1") ; - __CPROVER_assert(global==2, "global==2") ; + __CPROVER_assert(i == 1, "i==1"); + __CPROVER_assert(global == 2, "global==2"); } void pointer_test() @@ -38,37 +38,37 @@ void pointer_test() int j = 1; pointer_function(&i, 10); - __CPROVER_assert(j==1, "j==1"); - __CPROVER_assert(i==10, "i==10"); + __CPROVER_assert(j == 1, "j==1"); + __CPROVER_assert(i == 10, "i==10"); - j=2; + j = 2; pointer_function(&i, 10); - __CPROVER_assert(j==2, "j==2"); - __CPROVER_assert(i==10, "i==10"); + __CPROVER_assert(j == 2, "j==2"); + __CPROVER_assert(i == 10, "i==10"); - j=3; + j = 3; pointer_function(&i, 11); - __CPROVER_assert(j==3, "j==3"); - __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function + __CPROVER_assert(j == 3, "j==3"); + __CPROVER_assert( + i == 11, "i==11"); // unknown since value has top for pointer_function - j=4; + j = 4; pointer_function(&i, 478); - __CPROVER_assert(j==4, "j==4"); - __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function + __CPROVER_assert(j == 4, "j==4"); + __CPROVER_assert( + i == 11, "i==11"); // unknown since value has top for pointer_function } void global_test() { global = 0; modify_global_function(42); - __CPROVER_assert(global==42, "global==42"); + __CPROVER_assert(global == 42, "global==42"); modify_global_function(50); - __CPROVER_assert(global==50, "global==50"); // unknown since new_val will be top + __CPROVER_assert( + global == 50, "global==50"); // unknown since new_val will be top } - - - diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/main.c index eaddbedf304..d5f1909a364 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/main.c @@ -7,9 +7,9 @@ void simple_function(void) int j = 0; } -void pointer_function(int * write_to, int value) +void pointer_function(int *write_to, int value) { - *write_to=value; + *write_to = value; } void modify_global_function(int new_val) @@ -22,14 +22,14 @@ void simple_test() int i = 0; global = 0; simple_function(); - __CPROVER_assert(i==0, "i==0"); - __CPROVER_assert(global==0, "global==0"); + __CPROVER_assert(i == 0, "i==0"); + __CPROVER_assert(global == 0, "global==0"); i = 1; global = 2; simple_function(); - __CPROVER_assert(i==1, "i==1") ; - __CPROVER_assert(global==2, "global==2") ; + __CPROVER_assert(i == 1, "i==1"); + __CPROVER_assert(global == 2, "global==2"); } void pointer_test() @@ -38,37 +38,37 @@ void pointer_test() int j = 1; pointer_function(&i, 10); - __CPROVER_assert(j==1, "j==1"); - __CPROVER_assert(i==10, "i==10"); + __CPROVER_assert(j == 1, "j==1"); + __CPROVER_assert(i == 10, "i==10"); - j=2; + j = 2; pointer_function(&i, 10); - __CPROVER_assert(j==2, "j==2"); - __CPROVER_assert(i==10, "i==10"); + __CPROVER_assert(j == 2, "j==2"); + __CPROVER_assert(i == 10, "i==10"); - j=3; + j = 3; pointer_function(&i, 11); - __CPROVER_assert(j==3, "j==3"); - __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function + __CPROVER_assert(j == 3, "j==3"); + __CPROVER_assert( + i == 11, "i==11"); // unknown since value has top for pointer_function - j=4; + j = 4; pointer_function(&i, 478); - __CPROVER_assert(j==4, "j==4"); - __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function + __CPROVER_assert(j == 4, "j==4"); + __CPROVER_assert( + i == 11, "i==11"); // unknown since value has top for pointer_function } void global_test() { global = 0; modify_global_function(42); - __CPROVER_assert(global==42, "global==42"); + __CPROVER_assert(global == 42, "global==42"); modify_global_function(50); - __CPROVER_assert(global==50, "global==50"); // unknown since new_val will be top + __CPROVER_assert( + global == 50, "global==50"); // unknown since new_val will be top } - - - diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/main.c index eaddbedf304..d5f1909a364 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/main.c @@ -7,9 +7,9 @@ void simple_function(void) int j = 0; } -void pointer_function(int * write_to, int value) +void pointer_function(int *write_to, int value) { - *write_to=value; + *write_to = value; } void modify_global_function(int new_val) @@ -22,14 +22,14 @@ void simple_test() int i = 0; global = 0; simple_function(); - __CPROVER_assert(i==0, "i==0"); - __CPROVER_assert(global==0, "global==0"); + __CPROVER_assert(i == 0, "i==0"); + __CPROVER_assert(global == 0, "global==0"); i = 1; global = 2; simple_function(); - __CPROVER_assert(i==1, "i==1") ; - __CPROVER_assert(global==2, "global==2") ; + __CPROVER_assert(i == 1, "i==1"); + __CPROVER_assert(global == 2, "global==2"); } void pointer_test() @@ -38,37 +38,37 @@ void pointer_test() int j = 1; pointer_function(&i, 10); - __CPROVER_assert(j==1, "j==1"); - __CPROVER_assert(i==10, "i==10"); + __CPROVER_assert(j == 1, "j==1"); + __CPROVER_assert(i == 10, "i==10"); - j=2; + j = 2; pointer_function(&i, 10); - __CPROVER_assert(j==2, "j==2"); - __CPROVER_assert(i==10, "i==10"); + __CPROVER_assert(j == 2, "j==2"); + __CPROVER_assert(i == 10, "i==10"); - j=3; + j = 3; pointer_function(&i, 11); - __CPROVER_assert(j==3, "j==3"); - __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function + __CPROVER_assert(j == 3, "j==3"); + __CPROVER_assert( + i == 11, "i==11"); // unknown since value has top for pointer_function - j=4; + j = 4; pointer_function(&i, 478); - __CPROVER_assert(j==4, "j==4"); - __CPROVER_assert(i==11, "i==11"); // unknown since value has top for pointer_function + __CPROVER_assert(j == 4, "j==4"); + __CPROVER_assert( + i == 11, "i==11"); // unknown since value has top for pointer_function } void global_test() { global = 0; modify_global_function(42); - __CPROVER_assert(global==42, "global==42"); + __CPROVER_assert(global == 42, "global==42"); modify_global_function(50); - __CPROVER_assert(global==50, "global==50"); // unknown since new_val will be top + __CPROVER_assert( + global == 50, "global==50"); // unknown since new_val will be top } - - - diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c index 5dffda89aa4..7d4bcb60cd5 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/main.c @@ -1,43 +1,46 @@ -struct human { - int age; - float height; +struct human +{ + int age; + float height; }; -struct human another_human = { 18, 1.73 }; +struct human another_human = {18, 1.73}; void param_function(struct human a_human) { - __CPROVER_assert(a_human.age==24, "a_human.age==24"); - __CPROVER_assert(a_human.height==1.80, "a_human.height==1.80"); + __CPROVER_assert(a_human.age == 24, "a_human.age==24"); + __CPROVER_assert(a_human.height == 1.80, "a_human.height==1.80"); } void param_function_val(struct human *a_human, int val) { - a_human->age = val; + a_human->age = val; } - void pass_param() { - struct human human_instance; - human_instance.age = 24; - human_instance.height = 1.80f; - __CPROVER_assert(human_instance.age==24, "human_instance.age==24"); - __CPROVER_assert(human_instance.height==1.80f, "human_instance.height==1.80"); - param_function_val(&human_instance, 10); - - __CPROVER_assert(human_instance.age==10, "human_instance.age==10"); - __CPROVER_assert(human_instance.age==24, "human_instance.age==24"); - __CPROVER_assert(human_instance.height==1.80f, "human_instance.height==1.80"); - - param_function_val(&human_instance, 32); - __CPROVER_assert(human_instance.age==32, "human_instance.age==32"); - __CPROVER_assert(human_instance.age==10, "human_instance.age==10"); - __CPROVER_assert(human_instance.height==1.80f, "human_instance.height==1.80"); + struct human human_instance; + human_instance.age = 24; + human_instance.height = 1.80f; + __CPROVER_assert(human_instance.age == 24, "human_instance.age==24"); + __CPROVER_assert( + human_instance.height == 1.80f, "human_instance.height==1.80"); + param_function_val(&human_instance, 10); + + __CPROVER_assert(human_instance.age == 10, "human_instance.age==10"); + __CPROVER_assert(human_instance.age == 24, "human_instance.age==24"); + __CPROVER_assert( + human_instance.height == 1.80f, "human_instance.height==1.80"); + + param_function_val(&human_instance, 32); + __CPROVER_assert(human_instance.age == 32, "human_instance.age==32"); + __CPROVER_assert(human_instance.age == 10, "human_instance.age==10"); + __CPROVER_assert( + human_instance.height == 1.80f, "human_instance.height==1.80"); } void global_struct_test() { - __CPROVER_assert(another_human.age==18, "another_human.age==18"); - __CPROVER_assert(another_human.height==1.73f, "another_human.height==1.73"); + __CPROVER_assert(another_human.age == 18, "another_human.age==18"); + __CPROVER_assert(another_human.height == 1.73f, "another_human.height==1.73"); } \ No newline at end of file diff --git a/regression/goto-analyzer/variable-sensitivity-bit-field-constants/main.c b/regression/goto-analyzer/variable-sensitivity-bit-field-constants/main.c index 013100b8895..ff8af481d95 100644 --- a/regression/goto-analyzer/variable-sensitivity-bit-field-constants/main.c +++ b/regression/goto-analyzer/variable-sensitivity-bit-field-constants/main.c @@ -1,6 +1,7 @@ -struct bitfield_struct { +struct bitfield_struct +{ unsigned char byte; - unsigned char bitfield:1; + unsigned char bitfield : 1; }; extern struct bitfield_struct bs; @@ -9,6 +10,6 @@ void main(void) { bs.byte = 10; bs.bitfield = 1; - __CPROVER_assert(bs.byte==10, "bs.byte==10"); - __CPROVER_assert(bs.bitfield==1, "bs.bitfield==1"); + __CPROVER_assert(bs.byte == 10, "bs.byte==10"); + __CPROVER_assert(bs.bitfield == 1, "bs.bitfield==1"); } diff --git a/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/main.c b/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/main.c index 013100b8895..ff8af481d95 100644 --- a/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/main.c +++ b/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/main.c @@ -1,6 +1,7 @@ -struct bitfield_struct { +struct bitfield_struct +{ unsigned char byte; - unsigned char bitfield:1; + unsigned char bitfield : 1; }; extern struct bitfield_struct bs; @@ -9,6 +10,6 @@ void main(void) { bs.byte = 10; bs.bitfield = 1; - __CPROVER_assert(bs.byte==10, "bs.byte==10"); - __CPROVER_assert(bs.bitfield==1, "bs.bitfield==1"); + __CPROVER_assert(bs.byte == 10, "bs.byte==10"); + __CPROVER_assert(bs.bitfield == 1, "bs.bitfield==1"); } diff --git a/regression/goto-analyzer/variable-sensitivity-bug-01/main.c b/regression/goto-analyzer/variable-sensitivity-bug-01/main.c index 4a41802bc39..54f89eed952 100644 --- a/regression/goto-analyzer/variable-sensitivity-bug-01/main.c +++ b/regression/goto-analyzer/variable-sensitivity-bug-01/main.c @@ -1,14 +1,14 @@ -struct st { - int a; - int b; +struct st +{ + int a; + int b; }; struct st sts_inf; -void func( struct st* inf); // no body +void func(struct st *inf); // no body void main(void) { - func(&sts_inf); // assertion failed here + func(&sts_inf); // assertion failed here } - diff --git a/regression/goto-analyzer/variable-sensitivity-bug-02/main.c b/regression/goto-analyzer/variable-sensitivity-bug-02/main.c index 5867c127507..a768b30cd4c 100644 --- a/regression/goto-analyzer/variable-sensitivity-bug-02/main.c +++ b/regression/goto-analyzer/variable-sensitivity-bug-02/main.c @@ -1,34 +1,34 @@ // map.c -int map(int t_x, int * p_map) // mismatch :( +int map(int t_x, int *p_map) // mismatch :( { int n = p_map[0]; int *p_map_x = &p_map[1]; - int *p_map_y = p_map_x + n ; // assertion failed here + int *p_map_y = p_map_x + n; // assertion failed here int i; - if (t_x < p_map_x[0]) + if(t_x < p_map_x[0]) return p_map_y[0]; - for (i=1; i 0) + if(in > 0) { arr[2] = arr[1]; } diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/file1.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph/file1.c index b69b7a06662..dc56693e452 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph/file1.c +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/file1.c @@ -1,4 +1,5 @@ -struct structt { +struct structt +{ int a; int b; }; @@ -10,10 +11,10 @@ int out1, out2, out3; void struct_task(void) { int i; - if (in == 1) + if(in == 1) st.a++; - if (in == 2) + if(in == 2) st.b++; out1 = st.a; diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/file2.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph/file2.c index 2a02b6b5e31..702c037f655 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph/file2.c +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/file2.c @@ -4,10 +4,10 @@ int out1, out2, out3; void array_task(void) { - if (in == 1) + if(in == 1) ar[0]++; - if (in == 2) + if(in == 2) ar[1]++; out1 = ar[0]; diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/main.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph/main.c index 4f81ab8bfd6..f11e8b48266 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph/main.c +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/main.c @@ -1,4 +1,5 @@ -struct structt { +struct structt +{ int a; int b; }; @@ -15,20 +16,20 @@ void array_task(void); void main(void) { - if (in == 1) + if(in == 1) st.a++; - if (in == 2) + if(in == 2) st.b++; out1 = st.a; out2 = st.b; out3 = st.a + st.b; - if (in == 1) + if(in == 1) ar[0]++; - if (out1 == 2) + if(out1 == 2) ar[1]++; out1 = ar[0]; @@ -39,7 +40,7 @@ void main(void) arr[1] = 2; arr[2] = 3; - if (in > 0) + if(in > 0) { arr[2] = arr[1]; } diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph15/main.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph15/main.c index f8e7aae8585..ffb8590fb31 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph15/main.c +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph15/main.c @@ -1,4 +1,4 @@ -int f2(int, const int*); +int f2(int, const int *); extern const int g_map[]; int g_out1; @@ -14,7 +14,7 @@ void main(void) t1 = g_in; t2 = f2(t1, g_map); - if (t2 >= 0) + if(t2 >= 0) g_out1 = t2; else g_out1 = 0; diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph16/main.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph16/main.c index d4624824fab..39542ee75ea 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph16/main.c +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph16/main.c @@ -1,4 +1,4 @@ -int f2(int, const int*); +int f2(int, const int *); extern const int g_map[]; int g_out1; diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph17/main.c b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/main.c index d348399ec7a..7ef25c7f352 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph17/main.c +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/main.c @@ -13,9 +13,9 @@ void main(void) g_a[2] = 3; i = 0; - if (g_in > 0) + if(g_in > 0) { - i=1; + i = 1; g_a[2] = g_a[1]; } diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/main.c index f3710813803..ab08a8125a1 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/main.c +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/main.c @@ -1,17 +1,20 @@ #include #include -struct Vec2 { +struct Vec2 +{ int x; int y; }; -void MakeZero(struct Vec2 *vec) { +void MakeZero(struct Vec2 *vec) +{ vec->x = 0; vec->y = 0; } -void MakeOne(struct Vec2 *vec) { +void MakeOne(struct Vec2 *vec) +{ vec->x = 1; vec->y = 1; } @@ -21,10 +24,13 @@ int main(void) struct Vec2 vec = {-10, 10}; struct Vec2 vecMinusTenAndTen = vec; int nondet_condition; - if(nondet_condition) { + if(nondet_condition) + { MakeZero(&vec); struct Vec2 vecZero = vec; - } else { + } + else + { MakeOne(&vec); struct Vec2 vecOne = vec; } diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-float/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-float/main.c index 78b6e53b0c2..b5e23018ece 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-float/main.c +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-float/main.c @@ -5,10 +5,13 @@ int main(void) float x = 0.0f; float zero = x; int nondet_condition; - if(nondet_condition) { + if(nondet_condition) + { x = 1.0f; float one = x; - } else { + } + else + { x = -1.0f; float minus_one = x; } diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/main.c index 10b6f41e7fc..cdaf3191c4e 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/main.c +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/main.c @@ -12,9 +12,9 @@ int main(void) bool b3; if(x) - b3 = true; + b3 = true; else - b3 = false; + b3 = false; int i = b3 ? 10 : 20; diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/main.c index 52e7476f814..325ceca964f 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/main.c +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/main.c @@ -14,5 +14,5 @@ void main(int argc, char *argv[]) if(x > y) z = 3; - __CPROVER_assert(z == 1, "x < y, z == 1"); + __CPROVER_assert(z == 1, "x < y, z == 1"); } diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values/main.c b/regression/goto-analyzer/variable-sensitivity-interval-values/main.c index be6bfc9dfd8..6f6d0c71cdd 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values/main.c +++ b/regression/goto-analyzer/variable-sensitivity-interval-values/main.c @@ -5,10 +5,13 @@ int main(void) int x = 0; int zero = x; int nondet_condition; - if(nondet_condition) { + if(nondet_condition) + { x = 1; int one = x; - } else { + } + else + { x = -1; int minus_one = x; } diff --git a/regression/goto-analyzer/write-stack-types/write-stack-address-of.c b/regression/goto-analyzer/write-stack-types/write-stack-address-of.c index f4b4649edd0..1d7331b84af 100644 --- a/regression/goto-analyzer/write-stack-types/write-stack-address-of.c +++ b/regression/goto-analyzer/write-stack-types/write-stack-address-of.c @@ -1,34 +1,36 @@ typedef unsigned short uint16; -struct st { +struct st +{ uint16 data1; } str1; -extern struct { +extern struct +{ struct st data2; } g_sts; void func1(uint16 a) { // Expect the assert to be 'Unknown' because we would expect 'a' to be TOP - // here because p->data1 passed in as argument should be TOP. + // here because p->data1 passed in as argument should be TOP. __CPROVER_assert(a == 0, "func1.a == 0"); } void func2(struct st *p) { - func1(p->data1); + func1(p->data1); } void main(void) { - const int s_map_data[] = { 2, 10, 20, 100, 110 }; + const int s_map_data[] = {2, 10, 20, 100, 110}; - int *p_map_x = &s_map_data[1]; - int *p_map_y = p_map_x + 1 ; + int *p_map_x = &s_map_data[1]; + int *p_map_y = p_map_x + 1; - // Tests that the write_stack handles &smap_data[1] - __CPROVER_assert(*p_map_y == 20, "*main.p_map_y == 20"); + // Tests that the write_stack handles &smap_data[1] + __CPROVER_assert(*p_map_y == 20, "*main.p_map_y == 20"); - func2(&g_sts.data2); + func2(&g_sts.data2); } diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 43aa2d2bf36..ab9cf30814d 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -5,26 +5,26 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ +#include #include -#include #include #include -#include +#include +#include #include +#include #include -#include #include -#include +#include #include -#include #include #include "abstract_enviroment.h" #include "abstract_object_statistics.h" #ifdef DEBUG -#include +# include #endif /*******************************************************************\ @@ -41,72 +41,72 @@ Function: abstract_environmentt::eval \*******************************************************************/ -abstract_object_pointert abstract_environmentt::eval( - const exprt &expr, const namespacet &ns) const +abstract_object_pointert +abstract_environmentt::eval(const exprt &expr, const namespacet &ns) const { if(bottom) return abstract_object_factory(expr.type(), ns, false, true); // first try to canonicalise, including constant folding - const exprt &simplified_expr=simplify_expr(expr, ns); + const exprt &simplified_expr = simplify_expr(expr, ns); - const irep_idt simplified_id=simplified_expr.id(); - if(simplified_id==ID_symbol) + 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.get_identifier()); + const auto &symbol_entry = map.find(symbol.get_identifier()); if(!symbol_entry.has_value()) { return abstract_object_factory(simplified_expr.type(), ns, true); } else { - abstract_object_pointert found_symbol_value=symbol_entry.value(); + abstract_object_pointert found_symbol_value = symbol_entry.value(); return found_symbol_value; } } - else if(simplified_id==ID_member) + else if(simplified_id == ID_member) { member_exprt member_expr(to_member_expr(simplified_expr)); const exprt &parent = member_expr.compound(); - abstract_object_pointert parent_abstract_object=eval(parent, ns); + abstract_object_pointert parent_abstract_object = eval(parent, ns); return parent_abstract_object->read(*this, member_expr, ns); } - else if(simplified_id==ID_address_of) + else if(simplified_id == ID_address_of) { - abstract_object_pointert pointer_object= + abstract_object_pointert pointer_object = abstract_object_factory(simplified_expr.type(), simplified_expr, ns); // Store the abstract object in the pointer return pointer_object; } - else if(simplified_id==ID_dereference) + else if(simplified_id == ID_dereference) { dereference_exprt dereference(to_dereference_expr(simplified_expr)); - abstract_object_pointert pointer_abstract_object= + abstract_object_pointert pointer_abstract_object = eval(dereference.pointer(), ns); return pointer_abstract_object->read(*this, nil_exprt(), ns); } - else if(simplified_id==ID_index) + else if(simplified_id == ID_index) { index_exprt index_expr(to_index_expr(simplified_expr)); - abstract_object_pointert array_abstract_object= + abstract_object_pointert array_abstract_object = eval(index_expr.array(), ns); return array_abstract_object->read(*this, index_expr, ns); } - else if(simplified_id==ID_array) + else if(simplified_id == ID_array) { return abstract_object_factory(simplified_expr.type(), simplified_expr, ns); } - else if(simplified_id==ID_struct) + else if(simplified_id == ID_struct) { return abstract_object_factory(simplified_expr.type(), simplified_expr, ns); } - else if(simplified_id==ID_constant) + else if(simplified_id == ID_constant) { return abstract_object_factory( simplified_expr.type(), to_constant_expr(simplified_expr), ns); @@ -115,7 +115,7 @@ abstract_object_pointert abstract_environmentt::eval( { // No special handling required by the abstract environment // delegate to the abstract object - if(simplified_expr.operands().size()>0) + if(simplified_expr.operands().size() > 0) { return eval_expression(simplified_expr, ns); } @@ -163,22 +163,24 @@ Function: abstract_environmentt::assign \*******************************************************************/ bool abstract_environmentt::assign( - const exprt &expr, const abstract_object_pointert value, const namespacet &ns) + const exprt &expr, + const abstract_object_pointert value, + const namespacet &ns) { PRECONDITION(value); if(value->is_bottom()) { - bool bottom_at_start=this->is_bottom(); + bool bottom_at_start = this->is_bottom(); this->make_bottom(); return !bottom_at_start; } - abstract_object_pointert lhs_value=nullptr; + 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; - std::stack stactions; // I'm not a continuation, honest guv' + 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) @@ -188,19 +190,18 @@ bool abstract_environmentt::assign( } else { - lhs_value=eval(s, ns); + lhs_value = eval(s, ns); break; } } if(!lhs_value) { - INVARIANT(s.id()==ID_symbol, "Have a symbol or a stack"); + INVARIANT(s.id() == ID_symbol, "Have a symbol or a stack"); const symbol_exprt &symbol_expr(to_symbol_expr(s)); if(!map.has_key(symbol_expr.get_identifier())) { - lhs_value=abstract_object_factory( - symbol_expr.type(), ns, true, false); + lhs_value = abstract_object_factory(symbol_expr.type(), ns, true, false); } else { @@ -213,37 +214,41 @@ bool abstract_environmentt::assign( // 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); + 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) + if(s.id() != ID_symbol) { throw "invalid l-value"; } // We can assign the AO directly to the symbol - final_value=value; + final_value = value; } - const typet &lhs_type=ns.follow(lhs_value->type()); - const typet &rhs_type=ns.follow(final_value->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 - INVARIANT(lhs_type==rhs_type, - "Assignment types must match" "\n" - "lhs_type :" + lhs_type.pretty() + "\n" - "rhs_type :" + rhs_type.pretty()); + INVARIANT( + lhs_type == rhs_type, + "Assignment types must match" + "\n" + "lhs_type :" + + lhs_type.pretty() + + "\n" + "rhs_type :" + + rhs_type.pretty()); // If LHS was directly the symbol - if(s.id()==ID_symbol) + if(s.id() == ID_symbol) { - symbol_exprt symbol_expr=to_symbol_expr(s); + symbol_exprt symbol_expr = to_symbol_expr(s); if(final_value != lhs_value) { @@ -287,10 +292,10 @@ abstract_object_pointert abstract_environmentt::write( bool merge_write) { PRECONDITION(!remaining_stack.empty()); - const exprt & next_expr=remaining_stack.top(); + const exprt &next_expr = remaining_stack.top(); remaining_stack.pop(); - const irep_idt &stack_head_id=next_expr.id(); + 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) @@ -298,17 +303,17 @@ 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 - if(stack_head_id==ID_index) + if(stack_head_id == ID_index) { return lhs->write( - *this, ns, remaining_stack, to_index_expr(next_expr), rhs, merge_write); + *this, ns, remaining_stack, to_index_expr(next_expr), rhs, merge_write); } - else if(stack_head_id==ID_member) + else if(stack_head_id == ID_member) { return lhs->write( *this, ns, remaining_stack, to_member_expr(next_expr), rhs, merge_write); } - else if(stack_head_id==ID_dereference) + else if(stack_head_id == ID_dereference) { return lhs->write( *this, ns, remaining_stack, nil_exprt(), rhs, merge_write); @@ -342,17 +347,18 @@ bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) // This should be enforced by the well-structured-ness of the // goto-program and the way assume is used. - PRECONDITION(expr.type().id()==ID_bool); + PRECONDITION(expr.type().id() == ID_bool); // Evaluate the expression abstract_object_pointert res = eval(expr, 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 { // Should be of the right type - INVARIANT(possibly_constant.type().id()==ID_bool, "simplication preserves type"); + INVARIANT( + possibly_constant.type().id() == ID_bool, "simplication preserves type"); if(possibly_constant.is_false()) { @@ -383,7 +389,6 @@ bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) return false; } - /*******************************************************************\ Function: abstract_environmentt::abstract_object_factory @@ -401,7 +406,10 @@ Function: abstract_environmentt::abstract_object_factory \*******************************************************************/ abstract_object_pointert abstract_environmentt::abstract_object_factory( - const typet &type, const namespacet &ns, bool top, bool bottom) const + const typet &type, + const namespacet &ns, + bool top, + bool bottom) const { exprt empty_constant_expr = nil_exprt(); return abstract_object_factory( @@ -424,7 +432,9 @@ 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 { return abstract_object_factory(type, false, false, e, *this, ns); } @@ -447,8 +457,12 @@ 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 abstract_environmentt &environment, const namespacet &ns) const + const typet &type, + bool top, + bool bottom, + const exprt &e, + const abstract_environmentt &environment, + const namespacet &ns) const { return variable_sensitivity_object_factoryt::instance().get_abstract_object( type, top, bottom, e, environment, ns); @@ -467,7 +481,6 @@ Function: abstract_environmentt::merge \*******************************************************************/ - #include bool abstract_environmentt::merge(const abstract_environmentt &env) @@ -481,7 +494,7 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) if(bottom) { - *this=env; + *this = env; return !env.bottom; } else if(env.bottom) @@ -492,18 +505,15 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) { // 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; + bool modified = false; decltype(env.map)::delta_viewt delta_view; env.map.get_delta_view(map, delta_view); for(const auto &entry : delta_view) { - bool object_modified=false; - abstract_object_pointert new_object = - abstract_objectt::merge( - entry.get_other_map_value(), - entry.m, - object_modified); - modified|=object_modified; + bool object_modified = false; + abstract_object_pointert new_object = abstract_objectt::merge( + entry.get_other_map_value(), entry.m, object_modified); + modified |= object_modified; map.replace(entry.k, new_object); } @@ -546,7 +556,7 @@ void abstract_environmentt::make_top() { // since we assume anything is not in the map is top this is sufficient map.clear(); - bottom=false; + bottom = false; } /*******************************************************************\ @@ -564,7 +574,7 @@ Function: abstract_environmentt::make_bottom void abstract_environmentt::make_bottom() { map.clear(); - bottom=true; + bottom = true; } /*******************************************************************\ @@ -661,15 +671,16 @@ bool abstract_environmentt::verify() const } abstract_object_pointert abstract_environmentt::eval_expression( - const exprt &e, const namespacet &ns) const + const exprt &e, + const namespacet &ns) const { // We create a temporary top abstract object (according to the // type of the expression), and call expression transform on it. // The value of the temporary abstract object is ignored, its // purpose is just to dispatch the expression transform call to // a concrete subtype of abstract_objectt. - abstract_object_pointert eval_obj=abstract_object_factory( - e.type(), ns, true); + abstract_object_pointert eval_obj = + abstract_object_factory(e.type(), ns, true); std::vector operands; @@ -696,7 +707,7 @@ Function: abstract_environmentt::erase void abstract_environmentt::erase(const symbol_exprt &expr) { - map.erase_if_exists(expr.get_identifier()); + map.erase_if_exists(expr.get_identifier()); } /*******************************************************************\ @@ -721,7 +732,8 @@ Function: abstract_environmentt::environment_diff std::vector abstract_environmentt::modified_symbols( - const abstract_environmentt &first, const abstract_environmentt &second) + const abstract_environmentt &first, + const abstract_environmentt &second) { // Find all symbols who have different write locations in each map std::vector symbols_diff; @@ -730,7 +742,7 @@ abstract_environmentt::modified_symbols( for(const auto &entry : view) { const auto second_entry = second.map.find(entry.first); - if (second_entry.has_value()) + if(second_entry.has_value()) { if(second_entry.value().get()->has_been_modified(entry.second)) { @@ -744,7 +756,7 @@ abstract_environmentt::modified_symbols( for(const auto &entry : second.map.get_view()) { const auto &second_entry = first.map.find(entry.first); - if (!second_entry.has_value()) + if(!second_entry.has_value()) { CHECK_RETURN(!entry.first.empty()); symbols_diff.push_back(entry.first); @@ -755,11 +767,13 @@ abstract_environmentt::modified_symbols( static std::size_t count_globals(const namespacet &ns) { - auto const& symtab = ns.get_symbol_table(); - auto val = std::count_if(symtab.begin(), symtab.end(), - [](const symbol_tablet::const_iteratort::value_type& sym) { - return sym.second.is_lvalue && sym.second.is_static_lifetime; - }); + auto const &symtab = ns.get_symbol_table(); + auto val = std::count_if( + symtab.begin(), + symtab.end(), + [](const symbol_tablet::const_iteratort::value_type &sym) { + return sym.second.is_lvalue && sym.second.is_static_lifetime; + }); return val; } @@ -781,8 +795,6 @@ abstract_environmentt::gather_statistics(const namespacet &ns) const return statistics; } -abstract_environmentt::abstract_environmentt() -: bottom(false) +abstract_environmentt::abstract_environmentt() : bottom(false) { - } diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 48083e8b1e5..1c73ef9b845 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -9,10 +9,10 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_ENVIROMENT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_ENVIROMENT_H +#include #include #include #include -#include #include #include "abstract_object_statistics.h" @@ -26,8 +26,8 @@ class abstract_environmentt using map_keyt = irep_idt; abstract_environmentt(); // These three are really the heart of the method - virtual abstract_object_pointert eval( - const exprt &expr, const namespacet &ns) const; + virtual abstract_object_pointert + eval(const exprt &expr, const namespacet &ns) const; virtual bool assign( const exprt &expr, const abstract_object_pointert value, @@ -46,12 +46,14 @@ class abstract_environmentt virtual abstract_object_pointert abstract_object_factory( const typet &type, const namespacet &ns, - bool top=true, - bool bottom=false) const; + 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); @@ -66,8 +68,8 @@ class abstract_environmentt bool is_bottom() const; bool is_top() const; - void output( - std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; + void output(std::ostream &out, const class ai_baset &ai, const namespacet &ns) + const; bool verify() const; @@ -81,8 +83,8 @@ class abstract_environmentt bool bottom; // 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; + virtual abstract_object_pointert + eval_expression(const exprt &e, const namespacet &ns) const; sharing_mapt map; diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index f0638dbf738..622f9e61218 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -12,13 +12,13 @@ #include #include +#include +#include +#include #include -#include #include +#include #include -#include -#include -#include #include "abstract_object.h" @@ -35,9 +35,10 @@ Function: abstract_objectt::abstract_objectt \*******************************************************************/ -abstract_objectt::abstract_objectt(const typet &type): -t(type), bottom(false), top(true) -{} +abstract_objectt::abstract_objectt(const typet &type) + : t(type), bottom(false), top(true) +{ +} /*******************************************************************\ @@ -55,8 +56,8 @@ Function: abstract_objectt::abstract_objectt \*******************************************************************/ -abstract_objectt::abstract_objectt(const typet &type, bool top, bool bottom): - t(type), bottom(bottom), top(top) +abstract_objectt::abstract_objectt(const typet &type, bool top, bool bottom) + : t(type), bottom(bottom), top(top) { PRECONDITION(!(top && bottom)); } @@ -69,9 +70,10 @@ abstract_objectt::abstract_objectt(const typet &type, bool top, bool bottom): abstract_objectt::abstract_objectt( const exprt &expr, const abstract_environmentt &environment, - const namespacet &ns): - t(expr.type()), bottom(false), top(true) -{} + const namespacet &ns) + : t(expr.type()), bottom(false), top(true) +{ +} /// Ctor for building object of types that differ from the types of input /// expressions @@ -83,9 +85,10 @@ abstract_objectt::abstract_objectt( const typet &type, const exprt &expr, const abstract_environmentt &environment, - const namespacet &ns): - t(type), bottom(false), top(true) -{} + const namespacet &ns) + : t(type), bottom(false), top(true) +{ +} /*******************************************************************\ @@ -118,8 +121,8 @@ Function: abstract_objectt::merge \*******************************************************************/ -abstract_object_pointert abstract_objectt::merge( - abstract_object_pointert other) const +abstract_object_pointert +abstract_objectt::merge(abstract_object_pointert other) const { return abstract_object_merge(other); } @@ -144,9 +147,9 @@ abstract_object_pointert abstract_objectt::abstract_object_merge( if(is_top() || other->bottom) return this->abstract_object_merge_internal(other); - internal_abstract_object_pointert merged=mutable_clone(); + internal_abstract_object_pointert merged = mutable_clone(); merged->make_top(); - merged->bottom=false; + merged->bottom = false; return merged->abstract_object_merge_internal(other); } @@ -231,7 +234,7 @@ abstract_object_pointert abstract_objectt::expression_transform( { exprt copy = expr; - for (exprt &op : copy.operands()) + for(exprt &op : copy.operands()) { abstract_object_pointert op_abstract_object = environment.eval(op, ns); const exprt &const_op = op_abstract_object->to_constant(); @@ -240,7 +243,7 @@ abstract_object_pointert abstract_objectt::expression_transform( simplify(copy, ns); - for (const exprt &op : copy.operands()) + for(const exprt &op : copy.operands()) { abstract_object_pointert op_abstract_object = environment.eval(op, ns); const exprt &const_op = op_abstract_object->to_constant(); @@ -382,7 +385,9 @@ Function: abstract_objectt::output \*******************************************************************/ void abstract_objectt::output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) const + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const { if(top) { @@ -422,10 +427,11 @@ abstract_object_pointert abstract_objectt::merge( abstract_object_pointert op2, bool &out_modifications) { - abstract_object_pointert result=op1->should_use_base_merge(op2)? - op1->abstract_object_merge(op2):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; + out_modifications = result != op1; return result; } @@ -462,10 +468,11 @@ abstract_object_pointert abstract_objectt::meet( abstract_object_pointert op2, bool &out_modifications) { - abstract_object_pointert result=op1->should_use_base_meet(op2)? - op1->abstract_object_meet(op2):op1->meet(op2); + abstract_object_pointert result = op1->should_use_base_meet(op2) + ? op1->abstract_object_meet(op2) + : op1->meet(op2); // If no modifications, we will return the original pointer - out_modifications=result!=op1; + out_modifications = result != op1; return result; } @@ -499,13 +506,14 @@ abstract_object_pointert abstract_objectt::update_location_context( } void abstract_objectt::dump_map( - std::ostream out, const abstract_objectt::shared_mapt &m) + std::ostream out, + const abstract_objectt::shared_mapt &m) { shared_mapt::viewt view; m.get_view(view); out << "{"; - bool first=true; + bool first = true; for(auto &item : view) { out << (first ? "" : ", ") << item.first; diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index c4ab9b28f0a..c34fe7a4695 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -32,24 +32,23 @@ #include #include +#include "abstract_object_statistics.h" #include #include #include -#include "abstract_object_statistics.h" class typet; class constant_exprt; class abstract_environmentt; class namespacet; -#define CLONE \ - virtual internal_abstract_object_pointert mutable_clone() const override \ - { \ - typedef std::remove_const::type \ - >::type current_typet; \ - return internal_abstract_object_pointert(new current_typet(*this)); \ - } \ - +#define CLONE \ + virtual internal_abstract_object_pointert mutable_clone() const override \ + { \ + typedef std::remove_const< \ + std::remove_reference::type>::type current_typet; \ + return internal_abstract_object_pointert(new current_typet(*this)); \ + } /* Merge is designed to allow different abstractions to be merged * gracefully. There are two real use-cases for this: @@ -69,14 +68,13 @@ class namespacet; * merge then it merges, otherwise it calls the parent merge. */ - -template -using sharing_ptrt=std::shared_ptr; // NOLINT(*) +template +using sharing_ptrt = std::shared_ptr; // NOLINT(*) typedef sharing_ptrt abstract_object_pointert; using abstract_object_visitedt = std::set; -class abstract_objectt:public std::enable_shared_from_this +class abstract_objectt : public std::enable_shared_from_this { public: explicit abstract_objectt(const typet &type); @@ -91,7 +89,9 @@ class abstract_objectt:public std::enable_shared_from_this const abstract_environmentt &environment, const namespacet &ns); - virtual ~abstract_objectt() {} + virtual ~abstract_objectt() + { + } const typet &type() const; virtual bool is_top() const; @@ -127,15 +127,17 @@ class abstract_objectt:public std::enable_shared_from_this bool merging_write) const; virtual void output( - std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; + std::ostream &out, + const class ai_baset &ai, + const namespacet &ns) const; typedef std::set locationst; typedef sharing_mapt shared_mapt; static void dump_map(std::ostream out, const shared_mapt &m); - static void dump_map_diff( - std::ostream out, const shared_mapt &m1, const shared_mapt &m2); + static void + dump_map_diff(std::ostream out, const shared_mapt &m1, const shared_mapt &m2); abstract_object_pointert clone() const { @@ -204,8 +206,8 @@ class abstract_objectt:public std::enable_shared_from_this */ struct abstract_object_visitort { - virtual abstract_object_pointert visit( - const abstract_object_pointert element) const = 0; + virtual abstract_object_pointert + visit(const abstract_object_pointert element) const = 0; }; /** @@ -219,9 +221,11 @@ class abstract_objectt:public std::enable_shared_from_this * \return A new abstract_object if it's contents is modifed, or this if * no modification is needed */ - virtual abstract_object_pointert visit_sub_elements( - const abstract_object_visitort &visitor) const - { return shared_from_this(); } + virtual abstract_object_pointert + visit_sub_elements(const abstract_object_visitort &visitor) const + { + return shared_from_this(); + } virtual size_t internal_hash() const { @@ -241,19 +245,23 @@ class abstract_objectt:public std::enable_shared_from_this // Hooks to allow a sub-class to perform its own operations on // setting/clearing top - virtual void make_top_internal() {} - virtual void clear_top_internal() {} + virtual void make_top_internal() + { + } + virtual void clear_top_internal() + { + } // Hook for a subclass to perform any additional operations as // part of an abstract_object_merge - virtual abstract_object_pointert abstract_object_merge_internal( - const abstract_object_pointert other) const; + virtual abstract_object_pointert + abstract_object_merge_internal(const abstract_object_pointert other) const; virtual abstract_object_pointert abstract_object_meet_internal(const abstract_object_pointert &other) const; protected: - template - using internal_sharing_ptrt=std::shared_ptr; + template + using internal_sharing_ptrt = std::shared_ptr; typedef internal_sharing_ptrt internal_abstract_object_pointert; @@ -264,8 +272,8 @@ class abstract_objectt:public std::enable_shared_from_this return internal_abstract_object_pointert(new abstract_objectt(*this)); } - abstract_object_pointert abstract_object_merge( - const abstract_object_pointert other) const; + abstract_object_pointert + abstract_object_merge(const abstract_object_pointert other) const; bool should_use_base_merge(const abstract_object_pointert other) const; @@ -277,27 +285,32 @@ class abstract_objectt:public std::enable_shared_from_this bool should_use_base_meet(const abstract_object_pointert &other) const; - template + template static bool merge_maps( const std::map &map1, const std::map &map2, std::map &out_map); - - template + template static bool merge_shared_maps( const sharing_mapt &map1, const sharing_mapt &map2, sharing_mapt &out_map); - - // The one exception is merge in descendant classes, which needs this - void make_top() { top=true; this->make_top_internal(); } - void clear_top() { top=false; this->clear_top_internal(); } + void make_top() + { + top = true; + this->make_top_internal(); + } + void clear_top() + { + top = false; + this->clear_top_internal(); + } }; -template +template bool abstract_objectt::merge_maps( const std::map &m1, const std::map &m2, @@ -307,7 +320,7 @@ bool abstract_objectt::merge_maps( typedef std::map abstract_object_mapt; - bool modified=false; + bool modified = false; std::vector> intersection_set; std::set_intersection( @@ -318,8 +331,7 @@ bool abstract_objectt::merge_maps( std::back_inserter(intersection_set), []( const std::pair &op1, - const std::pair &op2) - { + const std::pair &op2) { return op1.first < op2.first; }); @@ -327,39 +339,38 @@ bool abstract_objectt::merge_maps( { // merge entries - const abstract_object_pointert &v1=m1.at(entry.first); - const abstract_object_pointert &v2=m2.at(entry.first); - - bool changes=false; - abstract_object_pointert v_new=abstract_objectt::merge(v1, v2, changes); + const abstract_object_pointert &v1 = m1.at(entry.first); + const abstract_object_pointert &v2 = m2.at(entry.first); + bool changes = false; + abstract_object_pointert v_new = abstract_objectt::merge(v1, v2, changes); - modified|=changes; + modified |= changes; - out_map[entry.first]=v_new; + out_map[entry.first] = v_new; } return modified; } -template +template bool abstract_objectt::merge_shared_maps( const sharing_mapt &m1, const sharing_mapt &m2, sharing_mapt &out_map) { - bool modified=false; + bool modified = false; typename sharing_mapt:: - delta_viewt delta_view; + delta_viewt delta_view; m1.get_delta_view(m2, delta_view, true); for(auto &item : delta_view) { bool changes = false; - abstract_object_pointert v_new = abstract_objectt::merge( - item.m, item.get_other_map_value(), changes); - if (changes) + abstract_object_pointert v_new = + abstract_objectt::merge(item.m, item.get_other_map_value(), changes); + if(changes) { modified = true; out_map.replace(item.k, v_new); diff --git a/src/analyses/variable-sensitivity/abstract_value.cpp b/src/analyses/variable-sensitivity/abstract_value.cpp index 6a2f75a8c55..2000a0e8a77 100644 --- a/src/analyses/variable-sensitivity/abstract_value.cpp +++ b/src/analyses/variable-sensitivity/abstract_value.cpp @@ -26,9 +26,9 @@ Function: abstract_valuet::abstract_valuet \*******************************************************************/ -abstract_valuet::abstract_valuet(const typet &type): - abstract_objectt(type) -{} +abstract_valuet::abstract_valuet(const typet &type) : abstract_objectt(type) +{ +} /*******************************************************************\ @@ -46,9 +46,10 @@ Function: abstract_valuet::abstract_valuet \*******************************************************************/ -abstract_valuet::abstract_valuet(const typet &type, bool top, bool bottom): - abstract_objectt(type, top, bottom) -{} +abstract_valuet::abstract_valuet(const typet &type, bool top, bool bottom) + : abstract_objectt(type, top, bottom) +{ +} /*******************************************************************\ @@ -68,6 +69,7 @@ Function: abstract_valuet::abstract_valuet abstract_valuet::abstract_valuet( const exprt &expr, const abstract_environmentt &environment, - const namespacet &ns): - abstract_objectt(expr, environment, ns) -{} + 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 6f4ab8374c0..c0c819e36d0 100644 --- a/src/analyses/variable-sensitivity/abstract_value.h +++ b/src/analyses/variable-sensitivity/abstract_value.h @@ -10,8 +10,7 @@ #include - -class abstract_valuet:public abstract_objectt +class abstract_valuet : public abstract_objectt { public: explicit abstract_valuet(const typet &type); @@ -21,7 +20,9 @@ class abstract_valuet:public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - virtual ~abstract_valuet() {} + virtual ~abstract_valuet() + { + } protected: CLONE diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 6b93144250a..1e4b8e7c5fb 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -6,11 +6,10 @@ \*******************************************************************/ -#include -#include -#include #include "array_abstract_object.h" - +#include +#include +#include /*******************************************************************\ @@ -25,10 +24,10 @@ Function: array_abstract_objectt::array_abstract_objectt \*******************************************************************/ -array_abstract_objectt::array_abstract_objectt(const typet &t): - abstract_objectt(t) +array_abstract_objectt::array_abstract_objectt(const typet &t) + : abstract_objectt(t) { - PRECONDITION(t.id()==ID_array); + PRECONDITION(t.id() == ID_array); } /*******************************************************************\ @@ -48,10 +47,12 @@ Function: array_abstract_objectt::array_abstract_objectt \*******************************************************************/ array_abstract_objectt::array_abstract_objectt( - const typet &t, bool tp, bool bttm): - abstract_objectt(t, tp, bttm) + const typet &t, + bool tp, + bool bttm) + : abstract_objectt(t, tp, bttm) { - PRECONDITION(t.id()==ID_array); + PRECONDITION(t.id() == ID_array); } /*******************************************************************\ @@ -72,10 +73,10 @@ Function: array_abstract_objectt::array_abstract_objectt array_abstract_objectt::array_abstract_objectt( const exprt &e, const abstract_environmentt &environment, - const namespacet &ns): - abstract_objectt(e, environment, ns) + const namespacet &ns) + : abstract_objectt(e, environment, ns) { - PRECONDITION(e.type().id()==ID_array); + PRECONDITION(e.type().id() == ID_array); } /** @@ -126,7 +127,6 @@ abstract_object_pointert array_abstract_objectt::write( environment, ns, stack, to_index_expr(specifier), value, merging_write); } - /*******************************************************************\ Function: array_abstract_objectt::read_index @@ -145,10 +145,10 @@ Function: array_abstract_objectt::read_index abstract_object_pointert array_abstract_objectt::read_index( const abstract_environmentt &env, const index_exprt &index, - const namespacet& ns) const + const namespacet &ns) const { array_typet array_type(to_array_type(type())); - const typet &subtype=array_type.subtype(); + const typet &subtype = array_type.subtype(); // if we are bottom then so are the values in the array // otherwise the values are top @@ -200,8 +200,12 @@ sharing_ptrt array_abstract_objectt::write_index( } } -void array_abstract_objectt::get_statistics(abstract_object_statisticst &statistics, abstract_object_visitedt &visited, - const abstract_environmentt &env, const namespacet &ns) const { +void array_abstract_objectt::get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const +{ abstract_objectt::get_statistics(statistics, visited, env, ns); ++statistics.number_of_arrays; } diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index 281e397f650..f2dde76cb99 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -8,15 +8,13 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ARRAY_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ARRAY_ABSTRACT_OBJECT_H -#include #include +#include class abstract_environmentt; class index_exprt; - - -class array_abstract_objectt:public abstract_objectt +class array_abstract_objectt : public abstract_objectt { public: explicit array_abstract_objectt(const typet &type); @@ -39,8 +37,11 @@ class array_abstract_objectt:public abstract_objectt const abstract_object_pointert value, bool merging_write) const override; - void get_statistics(abstract_object_statisticst &statistics, abstract_object_visitedt &visited, - const abstract_environmentt &env, const namespacet &ns) const override; + void get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const override; protected: CLONE diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index e8ed95e40d6..d9f5f46deec 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -21,20 +21,23 @@ #include "abstract_enviroment.h" #include "constant_abstract_value.h" -constant_abstract_valuet::constant_abstract_valuet(typet t): - abstract_valuet(t), value() -{} +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(typet t, bool tp, bool bttm) + : abstract_valuet(t, tp, bttm), value() +{ +} constant_abstract_valuet::constant_abstract_valuet( const exprt e, const abstract_environmentt &environment, - const namespacet &ns): - abstract_valuet(e.type(), false, false), value(e) -{} + const namespacet &ns) + : abstract_valuet(e.type(), false, false), value(e) +{ +} abstract_object_pointert constant_abstract_valuet::expression_transform( const exprt &expr, @@ -62,8 +65,8 @@ abstract_object_pointert constant_abstract_valuet::expression_transform( // another to check if there are any top subexpressions left for(const exprt &op : adjusted_expr.operands()) { - abstract_object_pointert lhs_abstract_object=environment.eval(op, ns); - const exprt &lhs_value=lhs_abstract_object->to_constant(); + abstract_object_pointert lhs_abstract_object = environment.eval(op, ns); + const exprt &lhs_value = lhs_abstract_object->to_constant(); if(lhs_value.is_nil()) { // do not give up if a sub-expression is not a constant, @@ -153,7 +156,9 @@ exprt constant_abstract_valuet::to_constant() const } void constant_abstract_valuet::output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) const + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const { if(!is_top() && !is_bottom()) { @@ -180,10 +185,10 @@ Function: constant_abstract_valuet::merge \*******************************************************************/ -abstract_object_pointert constant_abstract_valuet::merge( - abstract_object_pointert other) const +abstract_object_pointert +constant_abstract_valuet::merge(abstract_object_pointert other) const { - constant_abstract_value_pointert cast_other= + constant_abstract_value_pointert cast_other = std::dynamic_pointer_cast(other); if(cast_other) { @@ -221,7 +226,7 @@ abstract_object_pointert constant_abstract_valuet::merge_constant_constant( else { // Can we actually merge these value - if(value==other->value) + if(value == other->value) { return shared_from_this(); } @@ -232,10 +237,11 @@ abstract_object_pointert constant_abstract_valuet::merge_constant_constant( } } -void constant_abstract_valuet::get_statistics(abstract_object_statisticst &statistics, - abstract_object_visitedt &visited, - const abstract_environmentt &env, - const namespacet& ns) const +void constant_abstract_valuet::get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const { abstract_valuet::get_statistics(statistics, visited, env, ns); ++statistics.number_of_constants; diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 97bd230005c..83f5fd5e768 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 @@ -27,7 +27,9 @@ class constant_abstract_valuet:public abstract_valuet const abstract_environmentt &environment, const namespacet &ns); - virtual ~constant_abstract_valuet() {} + virtual ~constant_abstract_valuet() + { + } virtual abstract_object_pointert expression_transform( const exprt &expr, @@ -42,10 +44,11 @@ class constant_abstract_valuet:public abstract_valuet const class ai_baset &ai, const class namespacet &ns) const override; - void get_statistics(abstract_object_statisticst &statistics, - abstract_object_visitedt &visited, - const abstract_environmentt &env, - const namespacet& ns) const override; + void get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const override; size_t internal_hash() const override { @@ -61,17 +64,17 @@ class constant_abstract_valuet:public abstract_valuet protected: CLONE - virtual abstract_object_pointert merge( - abstract_object_pointert other) const override; + virtual abstract_object_pointert + merge(abstract_object_pointert other) const override; abstract_object_pointert try_transform_expr_with_all_rounding_modes( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns) const; -private : - abstract_object_pointert merge_constant_constant( - constant_abstract_value_pointert other) const; +private: + 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 9d4c2b2876d..22b3952a090 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -27,8 +27,8 @@ Function: constant_array_abstract_objectt::constant_array_abstract_objectt \*******************************************************************/ -constant_array_abstract_objectt::constant_array_abstract_objectt(typet type): -array_abstract_objectt(type) +constant_array_abstract_objectt::constant_array_abstract_objectt(typet type) + : array_abstract_objectt(type) { DATA_INVARIANT(verify(), "Structural invariants maintained"); } @@ -50,8 +50,10 @@ Function: constant_array_abstract_objectt::constant_array_abstract_objectt \*******************************************************************/ constant_array_abstract_objectt::constant_array_abstract_objectt( - typet type, bool top, bool bottom): -array_abstract_objectt(type, top, bottom) + typet type, + bool top, + bool bottom) + : array_abstract_objectt(type, top, bottom) { DATA_INVARIANT(verify(), "Structural invariants maintained"); } @@ -74,12 +76,12 @@ Function: constant_array_abstract_objectt::constant_array_abstract_objectt constant_array_abstract_objectt::constant_array_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, - const namespacet &ns): - array_abstract_objectt(expr, environment, ns) + const namespacet &ns) + : array_abstract_objectt(expr, environment, ns) { - if(expr.id()==ID_array) + if(expr.id() == ID_array) { - int index=0; + int index = 0; for(const exprt &entry : expr.operands()) { map.insert(mp_integer(index), environment.eval(entry, ns)); @@ -110,7 +112,7 @@ bool constant_array_abstract_objectt::verify() const // Either the object is top or bottom (=> map empty) // or the map is not empty => neither top nor bottom return array_abstract_objectt::verify() && - (is_top() || is_bottom()) == map.empty(); + (is_top() || is_bottom()) == map.empty(); } /// \brief Perform any additional structural modifications when setting this @@ -136,10 +138,10 @@ Function: constant_array_abstract_objectt::merge \*******************************************************************/ -abstract_object_pointert constant_array_abstract_objectt::merge( - abstract_object_pointert other) const +abstract_object_pointert +constant_array_abstract_objectt::merge(abstract_object_pointert other) const { - auto cast_other= + auto cast_other = std::dynamic_pointer_cast(other); if(cast_other) { @@ -176,8 +178,9 @@ abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( } else { - const auto &result= - std::dynamic_pointer_cast(mutable_clone()); + const auto &result = + std::dynamic_pointer_cast( + mutable_clone()); bool modified = abstract_objectt::merge_shared_maps( @@ -217,7 +220,9 @@ Function: constant_array_abstract_objectt::output \*******************************************************************/ void constant_array_abstract_objectt::output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) const + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const { if(is_top() || is_bottom()) { @@ -263,8 +268,7 @@ abstract_object_pointert constant_array_abstract_objectt::read_index( { if(is_top()) { - return env.abstract_object_factory( - index.type(), ns, true); + return env.abstract_object_factory(index.type(), ns, true); } else { @@ -331,13 +335,13 @@ Function: constant_array_abstract_objectt::write_index \*******************************************************************/ 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 +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()) { @@ -345,7 +349,7 @@ sharing_ptrt environment, ns, stack, index_expr, value, merging_write); } - const auto &result= + const auto &result = std::dynamic_pointer_cast(mutable_clone()); if(!stack.empty()) @@ -473,7 +477,8 @@ Function: constant_array_abstract_objectt::get_top_entry \*******************************************************************/ abstract_object_pointert constant_array_abstract_objectt::get_top_entry( - const abstract_environmentt &env, const namespacet &ns) const + const abstract_environmentt &env, + const namespacet &ns) const { return env.abstract_object_factory(type().subtype(), ns, true, false); } @@ -499,12 +504,12 @@ bool constant_array_abstract_objectt::eval_index( 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(); + 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); - bool result=to_integer(constant_index, out_index); + constant_exprt constant_index = to_constant_expr(value); + bool result = to_integer(constant_index, out_index); return !result; } else @@ -524,13 +529,11 @@ bool constant_array_abstract_objectt::eval_index( * \return A new abstract_object if it's contents is modifed, or this if * no modification is needed */ -abstract_object_pointert -constant_array_abstract_objectt::visit_sub_elements( +abstract_object_pointert constant_array_abstract_objectt::visit_sub_elements( const abstract_object_visitort &visitor) const { - const auto &result= - std::dynamic_pointer_cast( - mutable_clone()); + const auto &result = + std::dynamic_pointer_cast(mutable_clone()); bool modified = false; diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index 293686b3cdb..16883a79d0c 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -8,8 +8,8 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ARRAY_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ARRAY_ABSTRACT_OBJECT_H -#include #include +#include #include #include @@ -17,7 +17,7 @@ class ai_baset; class abstract_environmentt; -class constant_array_abstract_objectt:public array_abstract_objectt +class constant_array_abstract_objectt : public array_abstract_objectt { public: typedef sharing_ptrt const @@ -30,13 +30,15 @@ class constant_array_abstract_objectt:public array_abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - virtual ~constant_array_abstract_objectt() {} + virtual ~constant_array_abstract_objectt() + { + } - void output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; + void output(std::ostream &out, const ai_baset &ai, const namespacet &ns) + const override; - virtual abstract_object_pointert visit_sub_elements( - const abstract_object_visitort &visitor) const override; + virtual abstract_object_pointert + visit_sub_elements(const abstract_object_visitort &visitor) const override; void get_statistics( abstract_object_statisticst &statistics, @@ -60,8 +62,8 @@ class constant_array_abstract_objectt:public array_abstract_objectt const abstract_object_pointert value, bool merging_write) const override; - virtual abstract_object_pointert merge( - abstract_object_pointert other) const override; + virtual abstract_object_pointert + merge(abstract_object_pointert other) const override; virtual bool verify() const override; virtual void make_top_internal() override; @@ -78,19 +80,26 @@ class constant_array_abstract_objectt:public array_abstract_objectt // to the value at that index struct mp_integer_hash { - size_t operator()(const mp_integer &i) const { return std::hash{}(i.to_ulong()); } + size_t operator()(const mp_integer &i) const + { + return std::hash{}(i.to_ulong()); + } }; - typedef sharing_mapt + typedef sharing_mapt< + mp_integer, + abstract_object_pointert, + false, + mp_integer_hash> shared_array_mapt; shared_array_mapt map; - abstract_object_pointert get_top_entry( - const abstract_environmentt &env, const namespacet &ns) const; + abstract_object_pointert + get_top_entry(const abstract_environmentt &env, const namespacet &ns) const; - abstract_object_pointert constant_array_merge( - const constant_array_pointert other) const; + abstract_object_pointert + constant_array_merge(const constant_array_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 e2e2796738f..c147d465129 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -8,11 +8,11 @@ #include +#include "constant_pointer_abstract_object.h" +#include #include -#include #include -#include -#include "constant_pointer_abstract_object.h" +#include /*******************************************************************\ @@ -28,10 +28,10 @@ Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt \*******************************************************************/ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( - const typet &t): - pointer_abstract_objectt(t) + const typet &t) + : pointer_abstract_objectt(t) { - PRECONDITION(t.id()==ID_pointer); + PRECONDITION(t.id() == ID_pointer); } /*******************************************************************\ @@ -51,10 +51,12 @@ Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt \*******************************************************************/ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( - const typet &t, bool tp, bool bttm): - pointer_abstract_objectt(t, tp, bttm) + const typet &t, + bool tp, + bool bttm) + : pointer_abstract_objectt(t, tp, bttm) { - PRECONDITION(t.id()==ID_pointer); + PRECONDITION(t.id() == ID_pointer); } /*******************************************************************\ @@ -71,9 +73,10 @@ Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt \*******************************************************************/ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( - const constant_pointer_abstract_objectt &old): - pointer_abstract_objectt(old), value_stack(old.value_stack) -{} + const constant_pointer_abstract_objectt &old) + : pointer_abstract_objectt(old), value_stack(old.value_stack) +{ +} /*******************************************************************\ @@ -91,11 +94,11 @@ Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( const exprt &e, const abstract_environmentt &environment, - const namespacet &ns): - pointer_abstract_objectt(e, environment, ns), + const namespacet &ns) + : pointer_abstract_objectt(e, environment, ns), value_stack(e, environment, ns) { - PRECONDITION(e.type().id()==ID_pointer); + PRECONDITION(e.type().id() == ID_pointer); if(value_stack.is_top_value()) { make_top(); @@ -122,10 +125,10 @@ Function: constant_pointer_abstract_objectt::merge \*******************************************************************/ -abstract_object_pointert constant_pointer_abstract_objectt::merge( - abstract_object_pointert other) const +abstract_object_pointert +constant_pointer_abstract_objectt::merge(abstract_object_pointert other) const { - auto cast_other= + auto cast_other = std::dynamic_pointer_cast(other); if(cast_other) { @@ -155,8 +158,8 @@ Function: constant_pointer_abstract_objectt::merge_constant_pointers \*******************************************************************/ abstract_object_pointert - constant_pointer_abstract_objectt::merge_constant_pointers( - const constant_pointer_abstract_pointert other) const +constant_pointer_abstract_objectt::merge_constant_pointers( + const constant_pointer_abstract_pointert other) const { if(is_bottom()) { @@ -164,8 +167,8 @@ abstract_object_pointert } else { - bool matching_pointer= - value_stack.to_expression()==other->value_stack.to_expression(); + bool matching_pointer = + value_stack.to_expression() == other->value_stack.to_expression(); if(matching_pointer) { @@ -226,7 +229,9 @@ Function: constant_pointer_abstract_objectt::output \*******************************************************************/ void constant_pointer_abstract_objectt::output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) const + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const { if(is_top() || is_bottom() || value_stack.is_top_value()) { @@ -235,8 +240,8 @@ void constant_pointer_abstract_objectt::output( else { out << "ptr ->("; - const exprt &value=value_stack.to_expression(); - if(value.id()==ID_address_of) + const exprt &value = value_stack.to_expression(); + if(value.id() == ID_address_of) { const auto &addressee = to_address_of_expr(value).object(); if(addressee.id() == ID_symbol) @@ -284,7 +289,8 @@ Function: constant_pointer_abstract_objectt::read_dereference \*******************************************************************/ abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( - const abstract_environmentt &env, const namespacet &ns) const + const abstract_environmentt &env, + const namespacet &ns) const { if(is_top() || is_bottom() || value_stack.is_top_value()) { @@ -325,12 +331,12 @@ 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) const +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) const { if(is_top() || is_bottom() || value_stack.is_top_value()) { @@ -342,16 +348,15 @@ sharing_ptrt if(stack.empty()) { // We should not be changing the type of an abstract object - PRECONDITION(new_value->type()==ns.follow(type().subtype())); + PRECONDITION(new_value->type() == ns.follow(type().subtype())); // Get an expression that we can assign to - exprt value=value_stack.to_expression().op0(); + exprt value = value_stack.to_expression().op0(); if(merging_write) { - abstract_object_pointert pointed_value= - environment.eval(value, ns); + abstract_object_pointert pointed_value = environment.eval(value, ns); bool modifications; - abstract_object_pointert merged_value= + abstract_object_pointert merged_value = abstract_objectt::merge(pointed_value, new_value, modifications); environment.assign(value, merged_value, ns); } @@ -362,16 +367,16 @@ sharing_ptrt } else { - exprt value=value_stack.to_expression().op0(); - abstract_object_pointert pointed_value= - environment.eval(value, ns); - abstract_object_pointert modified_value= + exprt value = value_stack.to_expression().op0(); + abstract_object_pointert pointed_value = environment.eval(value, ns); + abstract_object_pointert modified_value = environment.write(pointed_value, new_value, stack, ns, merging_write); environment.assign(value, modified_value, ns); // but the pointer itself does not change! } - return std::dynamic_pointer_cast(shared_from_this()); + return std::dynamic_pointer_cast( + shared_from_this()); } } diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 399797396fe..782d18e39f0 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -13,18 +13,16 @@ #include #include -class constant_pointer_abstract_objectt:public pointer_abstract_objectt +class constant_pointer_abstract_objectt : public pointer_abstract_objectt { private: typedef sharing_ptrt constant_pointer_abstract_pointert; + public: explicit constant_pointer_abstract_objectt(const typet &type); - constant_pointer_abstract_objectt( - const typet &type, - bool top, - bool bottom); + constant_pointer_abstract_objectt(const typet &type, bool top, bool bottom); constant_pointer_abstract_objectt( const constant_pointer_abstract_objectt &old); @@ -35,11 +33,12 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt const namespacet &ns); exprt to_constant() const override; - void output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; + void output(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 override; + const abstract_environmentt &env, + const namespacet &ns) const override; sharing_ptrt write_dereference( abstract_environmentt &environment, @@ -55,14 +54,14 @@ class constant_pointer_abstract_objectt:public pointer_abstract_objectt const namespacet &ns) const override; protected: - virtual abstract_object_pointert merge( - abstract_object_pointert op1) const override; + virtual abstract_object_pointert + merge(abstract_object_pointert op1) const override; CLONE private: - abstract_object_pointert merge_constant_pointers( - const constant_pointer_abstract_pointert other) const; + abstract_object_pointert + merge_constant_pointers(const constant_pointer_abstract_pointert other) const; write_stackt value_stack; }; diff --git a/src/analyses/variable-sensitivity/context_abstract_object.cpp b/src/analyses/variable-sensitivity/context_abstract_object.cpp index a3e5a5fece1..b8d5dda02d3 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/context_abstract_object.cpp @@ -13,8 +13,7 @@ abstract_object_pointert context_abstract_objectt::get_child() const return child_abstract_object; } -void context_abstract_objectt::set_child( - const abstract_object_pointert &child) +void context_abstract_objectt::set_child(const abstract_object_pointert &child) { child_abstract_object = child; } @@ -77,18 +76,16 @@ abstract_object_pointert context_abstract_objectt::write( const abstract_object_pointert value, bool merging_write) const { - abstract_object_pointert updated_child= - child_abstract_object->write( - environment, ns, stack, specifier, value, merging_write); + abstract_object_pointert updated_child = child_abstract_object->write( + environment, ns, stack, specifier, value, merging_write); // Only perform an update if the write to the child has in fact changed it... if(updated_child == child_abstract_object) return shared_from_this(); // Need to ensure the result of the write is still wrapped in a context - const auto &result= - std::dynamic_pointer_cast( - mutable_clone()); + const auto &result = + std::dynamic_pointer_cast(mutable_clone()); // Update the child and record the updated write locations result->set_child(updated_child); @@ -109,10 +106,10 @@ abstract_object_pointert context_abstract_objectt::write( * \return the resolved expression */ abstract_object_pointert context_abstract_objectt::expression_transform( - const exprt &expr, - const std::vector &operands, - const abstract_environmentt &environment, - const namespacet &ns) const + const exprt &expr, + const std::vector &operands, + const abstract_environmentt &environment, + const namespacet &ns) const { PRECONDITION(expr.operands().size() == operands.size()); @@ -127,7 +124,7 @@ abstract_object_pointert context_abstract_objectt::expression_transform( auto p = std::dynamic_pointer_cast(op); INVARIANT(p, "Operand shall be of type context_abstract_objectt"); return p->child_abstract_object; - }); + }); return child_abstract_object->expression_transform( expr, child_operands, environment, ns); @@ -142,7 +139,9 @@ abstract_object_pointert context_abstract_objectt::expression_transform( * \param ns the current namespace */ void context_abstract_objectt::output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) const + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const { child_abstract_object->output(out, ai, ns); } @@ -161,9 +160,8 @@ bool context_abstract_objectt::has_been_modified( // Default implementation, with no other information to go on // falls back to relying on copy-on-write and pointer inequality // to indicate if an abstract_objectt has been modified - auto before_context= - std::dynamic_pointer_cast - (before); + auto before_context = + std::dynamic_pointer_cast(before); return this->child_abstract_object.get() != before_context->child_abstract_object.get(); diff --git a/src/analyses/variable-sensitivity/context_abstract_object.h b/src/analyses/variable-sensitivity/context_abstract_object.h index d1db479670e..2fbe2e83339 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.h +++ b/src/analyses/variable-sensitivity/context_abstract_object.h @@ -17,15 +17,15 @@ * instantiated directly - instead it is intended to be inherited from for * other classes to define what the context actually means. */ -class context_abstract_objectt: public abstract_objectt +class context_abstract_objectt : public abstract_objectt { public: // These constructors mirror those in the base abstract_objectt, but with // the addition of an extra argument which is the abstract_objectt to wrap. explicit context_abstract_objectt( const abstract_object_pointert child, - const typet &type): - abstract_objectt(type) + const typet &type) + : abstract_objectt(type) { child_abstract_object = child; } @@ -34,8 +34,8 @@ class context_abstract_objectt: public abstract_objectt const abstract_object_pointert child, const typet &type, bool top, - bool bottom): - abstract_objectt(type, top, bottom) + bool bottom) + : abstract_objectt(type, top, bottom) { child_abstract_object = child; } @@ -44,13 +44,15 @@ class context_abstract_objectt: public abstract_objectt const abstract_object_pointert child, const exprt &expr, const abstract_environmentt &environment, - const namespacet &ns): - abstract_objectt(expr, environment, ns) + const namespacet &ns) + : abstract_objectt(expr, environment, ns) { child_abstract_object = child; } - virtual ~context_abstract_objectt() {} + virtual ~context_abstract_objectt() + { + } virtual const typet &type() const { @@ -79,8 +81,9 @@ class context_abstract_objectt: public abstract_objectt const namespacet &ns) const override; virtual void output( - std::ostream &out, const class ai_baset &ai, const namespacet &ns) const - override; + std::ostream &out, + const class ai_baset &ai, + const namespacet &ns) const override; abstract_object_pointert unwrap_context() const override; @@ -98,8 +101,7 @@ class context_abstract_objectt: public abstract_objectt // The abstract_objectt that will be wrapped in a context abstract_object_pointert child_abstract_object; - void set_child( - const abstract_object_pointert &child); + void set_child(const abstract_object_pointert &child); // These are internal hooks that allow sub-classes to perform additional // actions when an abstract_object is set/unset to TOP @@ -119,8 +121,8 @@ class context_abstract_objectt: public abstract_objectt const abstract_object_pointert value, bool merging_write) const override; - virtual bool has_been_modified(const abstract_object_pointert before) const - override; + virtual bool + has_been_modified(const abstract_object_pointert before) const override; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONTEXT_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/data_dependency_context.cpp b/src/analyses/variable-sensitivity/data_dependency_context.cpp index 06dd3a50d31..86c335ec9ee 100644 --- a/src/analyses/variable-sensitivity/data_dependency_context.cpp +++ b/src/analyses/variable-sensitivity/data_dependency_context.cpp @@ -31,9 +31,8 @@ bool data_dependency_contextt::has_been_modified( if(this->write_location_contextt::has_been_modified(before)) return true; - auto cast_before= - std::dynamic_pointer_cast - (before); + auto cast_before = + std::dynamic_pointer_cast(before); if(!cast_before) { @@ -51,8 +50,8 @@ bool data_dependency_contextt::has_been_modified( cast_before->data_deps.cend(), std::inserter(intersection, intersection.end()), location_ordert()); - bool all_matched=intersection.size()==data_deps.size() && - intersection.size()==cast_before->data_deps.size(); + bool all_matched = intersection.size() == data_deps.size() && + intersection.size() == cast_before->data_deps.size(); if(!all_matched) return true; @@ -66,8 +65,8 @@ bool data_dependency_contextt::has_been_modified( std::inserter(intersection, intersection.end()), location_ordert()); - all_matched=intersection.size()==data_dominators.size() && - intersection.size()==cast_before->data_dominators.size(); + all_matched = intersection.size() == data_dominators.size() && + intersection.size() == cast_before->data_dominators.size(); return !all_matched; } @@ -108,7 +107,7 @@ abstract_object_pointert data_dependency_contextt::insert_data_deps( if(new_dependencies.empty()) return shared_from_this(); - const auto &result= + const auto &result = std::dynamic_pointer_cast(mutable_clone()); for(auto l : new_dependencies) @@ -136,8 +135,8 @@ abstract_object_pointert data_dependency_contextt::insert_data_deps( * \return a new data_dependency_context if new dependencies were set, * or 'this' if the dependencies were not changed. */ -abstract_object_pointert data_dependency_contextt::set_data_deps( - const dependencest &dependencies) const +abstract_object_pointert +data_dependency_contextt::set_data_deps(const dependencest &dependencies) const { // If the dependencies will not change, just return 'this' abstract_objectt::locationst intersection; @@ -149,12 +148,12 @@ abstract_object_pointert data_dependency_contextt::set_data_deps( dependencies.cend(), std::inserter(intersection, intersection.end()), location_ordert()); - if(intersection.size()==data_deps.size() && - intersection.size()==dependencies.size()) + if( + intersection.size() == data_deps.size() && + intersection.size() == dependencies.size()) return shared_from_this(); - - const auto &result= + const auto &result = std::dynamic_pointer_cast(mutable_clone()); result->data_deps = dependencies; @@ -197,7 +196,7 @@ abstract_object_pointert data_dependency_contextt::write( this->write_location_contextt::write( environment, ns, stack, specifier, value, merging_write)); - const auto cast_value= + const auto cast_value = std::dynamic_pointer_cast(value); return updated_parent->set_data_deps(cast_value->data_deps); @@ -214,8 +213,7 @@ abstract_object_pointert data_dependency_contextt::write( * \return a clone of this abstract object with it's location context * updated */ -abstract_object_pointert -data_dependency_contextt::update_location_context( +abstract_object_pointert data_dependency_contextt::update_location_context( const abstract_objectt::locationst &locations, const bool update_sub_elements) const { @@ -236,10 +234,10 @@ data_dependency_contextt::update_location_context( * \return the result of the merge, or 'this' if the merge would not change * the current abstract object */ -abstract_object_pointert data_dependency_contextt::merge( - abstract_object_pointert other) const +abstract_object_pointert +data_dependency_contextt::merge(abstract_object_pointert other) const { - auto cast_other= + auto cast_other = std::dynamic_pointer_cast(other); if(cast_other) @@ -252,9 +250,8 @@ abstract_object_pointert data_dependency_contextt::merge( std::dynamic_pointer_cast( merged_parent->insert_data_deps(cast_other->data_deps)); - const auto &result= - std::dynamic_pointer_cast( - updated_parent->mutable_clone()); + const auto &result = std::dynamic_pointer_cast( + updated_parent->mutable_clone()); // On a merge, data_dominators are the intersection of this object and the // other object. In other words, the dominators at this merge point are @@ -262,8 +259,10 @@ abstract_object_pointert data_dependency_contextt::merge( // merge point. result->data_dominators.clear(); std::set_intersection( - data_dominators.begin(), data_dominators.end(), - cast_other->data_dominators.begin(), cast_other->data_dominators.end(), + data_dominators.begin(), + data_dominators.end(), + cast_other->data_dominators.begin(), + cast_other->data_dominators.end(), std::inserter(result->data_dominators, result->data_dominators.end()), location_ordert()); @@ -296,7 +295,7 @@ abstract_object_pointert data_dependency_contextt::abstract_object_merge_internal( const abstract_object_pointert other) const { - auto other_context= + auto other_context = std::dynamic_pointer_cast(other); if(other_context) @@ -316,10 +315,11 @@ data_dependency_contextt::abstract_object_merge_internal( * \return set of data dependencies */ std::set - data_dependency_contextt::get_data_dependencies() const +data_dependency_contextt::get_data_dependencies() const { std::set result; - for (const auto d : data_deps) result.insert(d); + for(const auto d : data_deps) + result.insert(d); return result; } @@ -329,15 +329,18 @@ std::set * \return set of data dominators */ std::set - data_dependency_contextt::get_data_dominators() const +data_dependency_contextt::get_data_dominators() const { std::set result; - for (const auto d : data_dominators) result.insert(d); + for(const auto d : data_dominators) + result.insert(d); return result; } void data_dependency_contextt::output( - std::ostream &out, const class ai_baset &ai, const namespacet &ns) const + std::ostream &out, + const class ai_baset &ai, + const namespacet &ns) const { this->write_location_contextt::output(out, ai, ns); diff --git a/src/analyses/variable-sensitivity/data_dependency_context.h b/src/analyses/variable-sensitivity/data_dependency_context.h index 6cd7743d7af..c9532d8330a 100644 --- a/src/analyses/variable-sensitivity/data_dependency_context.h +++ b/src/analyses/variable-sensitivity/data_dependency_context.h @@ -17,15 +17,15 @@ Author: Diffblue Ltd #include "variable_sensitivity_domain.h" #include "write_location_context.h" -class data_dependency_contextt: - public write_location_contextt { +class data_dependency_contextt : public write_location_contextt +{ public: // These constructors mirror those in the base abstract_objectt, but with // the addition of an extra argument which is the abstract_objectt to wrap. explicit data_dependency_contextt( const abstract_object_pointert child, - const typet &type): - write_location_contextt(child, type) + const typet &type) + : write_location_contextt(child, type) { } @@ -33,8 +33,8 @@ class data_dependency_contextt: const abstract_object_pointert child, const typet &type, bool top, - bool bottom): - write_location_contextt(child, type, top, bottom) + bool bottom) + : write_location_contextt(child, type, top, bottom) { } @@ -42,8 +42,8 @@ class data_dependency_contextt: const abstract_object_pointert child, const exprt &expr, const abstract_environmentt &environment, - const namespacet &ns): - write_location_contextt(child, expr, environment, ns) + const namespacet &ns) + : write_location_contextt(child, expr, environment, ns) { } @@ -65,19 +65,19 @@ class data_dependency_contextt: std::set get_data_dominators() const; virtual void output( - std::ostream &out, const class ai_baset &ai, const namespacet &ns) const - override; + std::ostream &out, + const class ai_baset &ai, + const namespacet &ns) const override; protected: CLONE - virtual abstract_object_pointert merge( - abstract_object_pointert other) const override; + virtual abstract_object_pointert + merge(abstract_object_pointert other) const override; virtual abstract_object_pointert abstract_object_merge_internal( const abstract_object_pointert other) const override; - private: class location_ordert { @@ -86,19 +86,18 @@ class data_dependency_contextt: goto_programt::const_targett instruction, goto_programt::const_targett other_instruction) const { - return instruction->location_number> - other_instruction->location_number; + return instruction->location_number > other_instruction->location_number; } }; typedef std::set dependencest; dependencest data_deps; dependencest data_dominators; - abstract_object_pointert insert_data_deps( - const dependencest &dependencies) const; + abstract_object_pointert + insert_data_deps(const dependencest &dependencies) const; - abstract_object_pointert set_data_deps( - const dependencest &dependencies) const; + abstract_object_pointert + set_data_deps(const dependencest &dependencies) const; abstract_object_pointert insert_data_deps(const locationst &locations) const { @@ -115,7 +114,6 @@ class data_dependency_contextt: return set_data_deps(dependencies); } - }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_DATA_DEPENDENCY_CONTEXT_H diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index f161ff50d3f..49b16aaffd2 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -8,16 +8,16 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com #include -#include -#include #include +#include +#include #include "full_struct_abstract_object.h" // #define DEBUG #ifdef DEBUG -#include +# include #endif /** @@ -26,9 +26,10 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com * to ensure it shares as much data as possible. */ full_struct_abstract_objectt::full_struct_abstract_objectt( - const full_struct_abstract_objectt &ao): - struct_abstract_objectt(ao), map(ao.map) -{ } + const full_struct_abstract_objectt &ao) + : struct_abstract_objectt(ao), map(ao.map) +{ +} /*******************************************************************\ @@ -43,10 +44,10 @@ Function: full_struct_abstract_objectt::struct_abstract_objectt \*******************************************************************/ -full_struct_abstract_objectt::full_struct_abstract_objectt(const typet &t): - struct_abstract_objectt(t) +full_struct_abstract_objectt::full_struct_abstract_objectt(const typet &t) + : struct_abstract_objectt(t) { - PRECONDITION(t.id()==ID_struct); + PRECONDITION(t.id() == ID_struct); DATA_INVARIANT(verify(), "Structural invariants maintained"); } @@ -67,10 +68,12 @@ Function: struct_abstract_objectt::struct_abstract_objectt \*******************************************************************/ full_struct_abstract_objectt::full_struct_abstract_objectt( - const typet &t, bool top, bool bottom): - struct_abstract_objectt(t, top, bottom) + const typet &t, + bool top, + bool bottom) + : struct_abstract_objectt(t, top, bottom) { - PRECONDITION(t.id()==ID_struct); + PRECONDITION(t.id() == ID_struct); DATA_INVARIANT(verify(), "Structural invariants maintained"); } @@ -91,22 +94,21 @@ Function: full_struct_abstract_objectt::full_struct_abstract_objectt full_struct_abstract_objectt::full_struct_abstract_objectt( const exprt &e, const abstract_environmentt &environment, - const namespacet &ns): - struct_abstract_objectt(e, environment, ns) + const namespacet &ns) + : struct_abstract_objectt(e, environment, ns) { - PRECONDITION(ns.follow(e.type()).id()==ID_struct); + PRECONDITION(ns.follow(e.type()).id() == ID_struct); const struct_typet struct_type_def = to_struct_type(ns.follow(e.type())); bool did_initialize_values = false; auto struct_type_it = struct_type_def.components().begin(); - for(auto param_it = e.operands().begin(); - param_it != e.operands().end(); + for(auto param_it = e.operands().begin(); param_it != e.operands().end(); ++param_it) { map.insert_or_replace( struct_type_it->get_name(), - environment.abstract_object_factory (param_it->type(), *param_it, ns)); + environment.abstract_object_factory(param_it->type(), *param_it, ns)); did_initialize_values = true; ++struct_type_it; } @@ -140,7 +142,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 + const namespacet &ns) const { #ifdef DEBUG std::cout << "Reading component " << member_expr.get_component_name() @@ -149,14 +151,13 @@ abstract_object_pointert full_struct_abstract_objectt::read_component( if(is_top()) { - return environment.abstract_object_factory( - member_expr.type(), ns, true); + return environment.abstract_object_factory(member_expr.type(), ns, true); } else { PRECONDITION(!is_bottom()); - const irep_idt c=member_expr.get_component_name(); + const irep_idt c = member_expr.get_component_name(); auto const value = map.find(c); @@ -166,8 +167,7 @@ abstract_object_pointert full_struct_abstract_objectt::read_component( } else { - return environment.abstract_object_factory( - member_expr.type(), ns, true); + return environment.abstract_object_factory(member_expr.type(), ns, true); } } } @@ -194,13 +194,13 @@ 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 +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() @@ -214,22 +214,20 @@ sharing_ptrt member_expr.compound().type(), false, true)); } - const auto &result= + const auto &result = std::dynamic_pointer_cast(mutable_clone()); if(!stack.empty()) { abstract_object_pointert starting_value; - const irep_idt c=member_expr.get_component_name(); + const irep_idt c = member_expr.get_component_name(); auto const old_value = map.find(c); if(!old_value.has_value()) { - starting_value= - environment.abstract_object_factory( - member_expr.type(), ns, true, false); + starting_value = environment.abstract_object_factory( + member_expr.type(), ns, true, false); result->map.insert( - c, - environment.write(starting_value, value, stack, ns, merging_write)); + c, environment.write(starting_value, value, stack, ns, merging_write)); } else { @@ -244,12 +242,11 @@ sharing_ptrt } else { - #ifdef DEBUG std::cout << "Setting component" << std::endl; #endif - const irep_idt c=member_expr.get_component_name(); + const irep_idt c = member_expr.get_component_name(); auto const old_value = result->map.find(c); if(merging_write) @@ -312,7 +309,9 @@ Function: full_struct_abstract_objectt::output \*******************************************************************/ void full_struct_abstract_objectt::output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) const + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const { // To ensure that a consistent ordering of fields is output, use // the underlying type declaration for this struct to determine @@ -332,7 +331,8 @@ void full_struct_abstract_objectt::output( out << ", "; } out << '.' << field.get_name() << '='; - static_cast(value.value())->output(out, ai, ns); + static_cast(value.value()) + ->output(out, ai, ns); first = false; } } @@ -376,10 +376,10 @@ Function: full_struct_abstract_objectt::merge \*******************************************************************/ -abstract_object_pointert full_struct_abstract_objectt::merge( - abstract_object_pointert other) const +abstract_object_pointert +full_struct_abstract_objectt::merge(abstract_object_pointert other) const { - constant_struct_pointert cast_other= + constant_struct_pointert cast_other = std::dynamic_pointer_cast(other); if(cast_other) { @@ -416,7 +416,7 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( } else { - const auto &result= + const auto &result = std::dynamic_pointer_cast(mutable_clone()); bool modified = abstract_objectt::merge_shared_maps( @@ -451,7 +451,7 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( abstract_object_pointert full_struct_abstract_objectt::visit_sub_elements( const abstract_object_visitort &visitor) const { - const auto &result= + const auto &result = std::dynamic_pointer_cast(mutable_clone()); bool modified = false; diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index c3769c1e3b3..d55858e9e85 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -9,16 +9,16 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_FULL_STRUCT_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_FULL_STRUCT_ABSTRACT_OBJECT_H -#include -#include #include #include +#include +#include #include class abstract_environmentt; class member_exprt; -class full_struct_abstract_objectt:public struct_abstract_objectt +class full_struct_abstract_objectt : public struct_abstract_objectt { public: typedef sharing_ptrt constant_struct_pointert; @@ -40,8 +40,8 @@ class full_struct_abstract_objectt:public struct_abstract_objectt const class ai_baset &ai, const class namespacet &ns) const override; - virtual abstract_object_pointert visit_sub_elements( - const abstract_object_visitort &visitor) const override; + virtual abstract_object_pointert + visit_sub_elements(const abstract_object_visitort &visitor) const override; void get_statistics( abstract_object_statisticst &statistics, @@ -55,8 +55,8 @@ class full_struct_abstract_objectt:public struct_abstract_objectt shared_struct_mapt; shared_struct_mapt map; - abstract_object_pointert merge_constant_structs( - constant_struct_pointert other) const; + abstract_object_pointert + merge_constant_structs(constant_struct_pointert other) const; protected: CLONE @@ -65,7 +65,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) const override; + const namespacet &ns) const override; virtual sharing_ptrt write_component( abstract_environmentt &environment, @@ -78,8 +78,8 @@ class full_struct_abstract_objectt:public struct_abstract_objectt virtual bool verify() const override; // Set the state of this to the merge result of op1 and op2 and // return if the result is different from op1 - virtual abstract_object_pointert 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 diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index 0cf9bdce46a..391ab4f63d1 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -6,8 +6,8 @@ \*******************************************************************/ -#include #include +#include #include #include @@ -175,17 +175,18 @@ static inline constant_interval_exprt interval_from_relation(const exprt &e) interval_abstract_valuet::interval_abstract_valuet(typet t) : abstract_valuet(t), interval(t) -{} +{ +} interval_abstract_valuet::interval_abstract_valuet(typet t, bool tp, bool bttm) : abstract_valuet(t, tp, bttm), interval(t) -{} +{ +} interval_abstract_valuet::interval_abstract_valuet( const constant_interval_exprt e) : interval_abstract_valuet(e, 0) { - } exprt interval_abstract_valuet::to_constant() const @@ -223,9 +224,8 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( for(const auto &op : operands) { - auto iav - = std::dynamic_pointer_cast(op); - if (!iav) + auto iav = std::dynamic_pointer_cast(op); + if(!iav) { // The operand isn't an interval - if it's an integral constant we can // convert it into an interval. @@ -288,7 +288,8 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( interval = interval.plus(interval_next); } - INVARIANT(interval.type() == type, + INVARIANT( + interval.type() == type, "Type of result interval should match expression type"); return environment.abstract_object_factory(type, interval, ns); @@ -301,10 +302,11 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( { const typecast_exprt &tce = to_typecast_expr(expr); - const constant_interval_exprt &new_interval - = interval.typecast(tce.type()); + const constant_interval_exprt &new_interval = + interval.typecast(tce.type()); - INVARIANT(new_interval.type() == type, + INVARIANT( + new_interval.type() == type, "Type of result interval should match expression type"); return environment.abstract_object_factory(tce.type(), new_interval, ns); @@ -312,7 +314,8 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( else { const constant_interval_exprt &interval_result = interval.eval(expr.id()); - INVARIANT(interval_result.type() == type, + INVARIANT( + interval_result.type() == type, "Type of result interval should match expression type"); return environment.abstract_object_factory(type, interval_result, ns); } @@ -322,10 +325,10 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( const constant_interval_exprt &interval0 = interval_operands[0]->interval; const constant_interval_exprt &interval1 = interval_operands[1]->interval; - constant_interval_exprt interval - = interval0.eval(expr.id(), interval1); + constant_interval_exprt interval = interval0.eval(expr.id(), interval1); - INVARIANT(interval.type() == type, + INVARIANT( + interval.type() == type, "Type of result interval should match expression type"); return environment.abstract_object_factory(type, interval, ns); @@ -334,28 +337,36 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( { if(expr.id() == ID_if) { - const constant_interval_exprt &condition_interval = interval_operands[0]->interval; - const constant_interval_exprt &true_interval = interval_operands[1]->interval; - const constant_interval_exprt &false_interval = interval_operands[2]->interval; + const constant_interval_exprt &condition_interval = + interval_operands[0]->interval; + const constant_interval_exprt &true_interval = + interval_operands[1]->interval; + const constant_interval_exprt &false_interval = + interval_operands[2]->interval; // Check the value of the condition interval - if(condition_interval.is_definitely_false().is_unknown()) { + if(condition_interval.is_definitely_false().is_unknown()) + { // Value of the condition is both true and false, so // combine the intervals of both the true and false expressions return environment.abstract_object_factory( type, constant_interval_exprt( - constant_interval_exprt::get_min(true_interval.get_lower(), false_interval.get_lower()), - constant_interval_exprt::get_max(true_interval.get_upper(), false_interval.get_upper())), + constant_interval_exprt::get_min( + true_interval.get_lower(), false_interval.get_lower()), + constant_interval_exprt::get_max( + true_interval.get_upper(), false_interval.get_upper())), ns); } - if(condition_interval.is_definitely_false().is_true()) { + if(condition_interval.is_definitely_false().is_true()) + { // The condition is definitely false, so return only // the interval from the 'false' expression return environment.abstract_object_factory( false_interval.type(), false_interval, ns); } - if(condition_interval.is_definitely_true().is_true()) { + if(condition_interval.is_definitely_true().is_true()) + { // The condition is definitely true, so return only // the interval from the 'true' expression return environment.abstract_object_factory( @@ -368,27 +379,39 @@ abstract_object_pointert interval_abstract_valuet::expression_transform( } void interval_abstract_valuet::output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) const + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const { if(!is_top() && !is_bottom()) { std::string lower_string; std::string upper_string; - if(interval.get_lower().id() == ID_min) { + if(interval.get_lower().id() == ID_min) + { lower_string = "-INF"; - } else { - INVARIANT(interval.get_lower().id() == ID_constant, - "We only support constant limits"); - lower_string = id2string(to_constant_expr(interval.get_lower()).get_value()); + } + else + { + INVARIANT( + interval.get_lower().id() == ID_constant, + "We only support constant limits"); + lower_string = + id2string(to_constant_expr(interval.get_lower()).get_value()); } - if(interval.get_upper().id() == ID_max) { + if(interval.get_upper().id() == ID_max) + { upper_string = "+INF"; - } else { - INVARIANT(interval.get_lower().id() == ID_constant, - "We only support constant limits"); - upper_string = id2string(to_constant_expr(interval.get_upper()).get_value()); + } + else + { + INVARIANT( + interval.get_lower().id() == ID_constant, + "We only support constant limits"); + upper_string = + id2string(to_constant_expr(interval.get_upper()).get_value()); } out << "[" << lower_string << ", " << upper_string << "]"; @@ -399,10 +422,10 @@ void interval_abstract_valuet::output( } } -abstract_object_pointert interval_abstract_valuet::merge( - abstract_object_pointert other) const +abstract_object_pointert +interval_abstract_valuet::merge(abstract_object_pointert other) const { - interval_abstract_value_pointert cast_other= + interval_abstract_value_pointert cast_other = std::dynamic_pointer_cast(other); if(cast_other) { diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h index 5e0c9f57fb8..d26fa49dcef 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.h +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -16,7 +16,7 @@ #include #include -class interval_abstract_valuet:public abstract_valuet +class interval_abstract_valuet : public abstract_valuet { private: typedef sharing_ptrt @@ -28,8 +28,7 @@ class interval_abstract_valuet:public abstract_valuet interval_abstract_valuet(const constant_interval_exprt e, int merge_count); - explicit interval_abstract_valuet( - const constant_interval_exprt e); + explicit interval_abstract_valuet(const constant_interval_exprt e); interval_abstract_valuet( const exprt e, @@ -62,16 +61,16 @@ class interval_abstract_valuet:public abstract_valuet protected: CLONE - virtual abstract_object_pointert merge( - abstract_object_pointert other) const override; + virtual abstract_object_pointert + merge(abstract_object_pointert other) const override; abstract_object_pointert meet(const abstract_object_pointert &other) const override; -private : - abstract_object_pointert merge_intervals( - interval_abstract_value_pointert other) const; - abstract_object_pointert meet_intervals( - interval_abstract_value_pointert other) const; +private: + abstract_object_pointert + merge_intervals(interval_abstract_value_pointert other) const; + abstract_object_pointert + meet_intervals(interval_abstract_value_pointert other) const; constant_interval_exprt interval; diff --git a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp index 8ff21fd4b0a..e40225c8f47 100644 --- a/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/interval_array_abstract_object.cpp @@ -77,7 +77,8 @@ interval_array_abstract_objectt::write_index( auto ix = index_interval.get_lower(); auto interval_end = index_interval.get_upper(); sharing_ptrt result = shared_from_this(); - while(!result->is_top() && simplify_expr(binary_predicate_exprt(ix, ID_gt, interval_end), ns) + while(!result->is_top() && + simplify_expr(binary_predicate_exprt(ix, ID_gt, interval_end), ns) .is_false()) { auto array_after_write_at_index = @@ -113,7 +114,8 @@ abstract_object_pointert interval_array_abstract_objectt::read_index( auto ix = index_interval.get_lower(); auto interval_end = index_interval.get_upper(); abstract_object_pointert value; - while((!value || !value->is_top()) && simplify_expr(binary_relation_exprt(ix, ID_gt, interval_end), ns) + while((!value || !value->is_top()) && + simplify_expr(binary_relation_exprt(ix, ID_gt, interval_end), ns) .is_false()) { auto value_at_index = constant_array_abstract_objectt::read_index( diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index 9c0a7055a1b..e8c6e45404e 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -5,14 +5,13 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ -#include #include +#include #include #include "pointer_abstract_object.h" - /*******************************************************************\ Function: pointer_abstract_objectt::pointer_abstract_objectt @@ -26,10 +25,10 @@ Function: pointer_abstract_objectt::pointer_abstract_objectt \*******************************************************************/ -pointer_abstract_objectt::pointer_abstract_objectt(const typet &t): - abstract_objectt(t) +pointer_abstract_objectt::pointer_abstract_objectt(const typet &t) + : abstract_objectt(t) { - PRECONDITION(t.id()==ID_pointer); + PRECONDITION(t.id() == ID_pointer); } /*******************************************************************\ @@ -49,10 +48,12 @@ Function: pointer_abstract_objectt::pointer_abstract_objectt \*******************************************************************/ pointer_abstract_objectt::pointer_abstract_objectt( - const typet &t, bool tp, bool bttm): - abstract_objectt(t, tp, bttm) + const typet &t, + bool tp, + bool bttm) + : abstract_objectt(t, tp, bttm) { - PRECONDITION(t.id()==ID_pointer); + PRECONDITION(t.id() == ID_pointer); } /*******************************************************************\ @@ -71,10 +72,10 @@ Function: pointer_abstract_objectt::pointer_abstract_objectt pointer_abstract_objectt::pointer_abstract_objectt( const exprt &e, const abstract_environmentt &environment, - const namespacet &ns): - abstract_objectt(e, environment, ns) + const namespacet &ns) + : abstract_objectt(e, environment, ns) { - PRECONDITION(e.type().id()==ID_pointer); + PRECONDITION(e.type().id() == ID_pointer); } /** @@ -140,10 +141,11 @@ Function: pointer_abstract_objectt::read_dereference \*******************************************************************/ abstract_object_pointert pointer_abstract_objectt::read_dereference( - const abstract_environmentt &env, const namespacet &ns) 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(); + const typet &pointed_to_type = pointer_type.subtype(); return env.abstract_object_factory(pointed_to_type, ns, true, false); } @@ -173,12 +175,12 @@ 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) const +pointer_abstract_objectt::write_dereference( + abstract_environmentt &environment, + const namespacet &ns, + const std::stack stack, + const abstract_object_pointert value, + bool merging_write) const { if(is_top() || is_bottom()) { @@ -192,9 +194,12 @@ sharing_ptrt } } -void -pointer_abstract_objectt::get_statistics(abstract_object_statisticst &statistics, abstract_object_visitedt &visited, - const abstract_environmentt &env, const namespacet &ns) const { +void pointer_abstract_objectt::get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const +{ abstract_objectt::get_statistics(statistics, visited, env, ns); ++statistics.number_of_pointers; } diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index 49388a3ace6..6e908901e06 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -8,7 +8,6 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_POINTER_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_POINTER_ABSTRACT_OBJECT_H - #include #include @@ -17,7 +16,7 @@ class typet; class constant_exprt; class abstract_environmentt; -class pointer_abstract_objectt:public abstract_objectt +class pointer_abstract_objectt : public abstract_objectt { public: explicit pointer_abstract_objectt(const typet &type); @@ -40,15 +39,19 @@ class pointer_abstract_objectt:public abstract_objectt const abstract_object_pointert value, bool merging_write) const override; - void get_statistics(abstract_object_statisticst &statistics, abstract_object_visitedt &visited, - const abstract_environmentt &env, const namespacet &ns) const override; + void get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const override; protected: CLONE // pointer interface virtual abstract_object_pointert read_dereference( - const abstract_environmentt &env, const namespacet &ns) const; + const abstract_environmentt &env, + const namespacet &ns) const; virtual sharing_ptrt write_dereference( abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index bae43e84673..f8cc4bde1ed 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -6,14 +6,13 @@ \*******************************************************************/ -#include -#include -#include #include +#include +#include +#include #include "struct_abstract_object.h" - /*******************************************************************\ Function: struct_abstract_objectt::struct_abstract_objectt @@ -27,10 +26,10 @@ Function: struct_abstract_objectt::struct_abstract_objectt \*******************************************************************/ -struct_abstract_objectt::struct_abstract_objectt(const typet &t): - abstract_objectt(t) +struct_abstract_objectt::struct_abstract_objectt(const typet &t) + : abstract_objectt(t) { - PRECONDITION(t.id()==ID_struct); + PRECONDITION(t.id() == ID_struct); } /*******************************************************************\ @@ -50,10 +49,12 @@ Function: struct_abstract_objectt::struct_abstract_objectt \*******************************************************************/ struct_abstract_objectt::struct_abstract_objectt( - const typet &t, bool tp, bool bttm): - abstract_objectt(t, tp, bttm) + const typet &t, + bool tp, + bool bttm) + : abstract_objectt(t, tp, bttm) { - PRECONDITION(t.id()==ID_struct); + PRECONDITION(t.id() == ID_struct); } /*******************************************************************\ @@ -72,10 +73,10 @@ Function: struct_abstract_objectt::struct_abstract_objectt struct_abstract_objectt::struct_abstract_objectt( const exprt &e, const abstract_environmentt &environment, - const namespacet &ns): - abstract_objectt(e, environment, ns) + const namespacet &ns) + : abstract_objectt(e, environment, ns) { - PRECONDITION(ns.follow(e.type()).id()==ID_struct); + PRECONDITION(ns.follow(e.type()).id() == ID_struct); } /** @@ -147,7 +148,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 + const namespacet &ns) const { // If we are bottom then so are the components // otherwise the components could be anything @@ -194,8 +195,12 @@ sharing_ptrt struct_abstract_objectt::write_component( } } -void struct_abstract_objectt::get_statistics(abstract_object_statisticst &statistics, abstract_object_visitedt &visited, - const abstract_environmentt &env, const namespacet &ns) const { +void struct_abstract_objectt::get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const +{ abstract_objectt::get_statistics(statistics, visited, env, ns); ++statistics.number_of_structs; } diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index 255e7464fc3..06155524221 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -9,13 +9,13 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H -#include #include +#include class abstract_environmentt; class member_exprt; -class struct_abstract_objectt:public abstract_objectt +class struct_abstract_objectt : public abstract_objectt { public: explicit struct_abstract_objectt(const typet &type); @@ -38,8 +38,11 @@ class struct_abstract_objectt:public abstract_objectt const abstract_object_pointert value, bool merging_write) const override; - void get_statistics(abstract_object_statisticst &statistics, abstract_object_visitedt &visited, - const abstract_environmentt &env, const namespacet &ns) const override; + void get_statistics( + abstract_object_statisticst &statistics, + abstract_object_visitedt &visited, + const abstract_environmentt &env, + const namespacet &ns) const override; protected: CLONE diff --git a/src/analyses/variable-sensitivity/union_abstract_object.cpp b/src/analyses/variable-sensitivity/union_abstract_object.cpp index 37ce932b35f..a00dc8da25c 100644 --- a/src/analyses/variable-sensitivity/union_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/union_abstract_object.cpp @@ -6,13 +6,12 @@ \*******************************************************************/ -#include -#include #include +#include +#include #include "union_abstract_object.h" - /*******************************************************************\ Function: union_abstract_objectt::union_abstract_objectt @@ -26,10 +25,10 @@ Function: union_abstract_objectt::union_abstract_objectt \*******************************************************************/ -union_abstract_objectt::union_abstract_objectt(const typet &type): - abstract_objectt(type) +union_abstract_objectt::union_abstract_objectt(const typet &type) + : abstract_objectt(type) { - PRECONDITION(type.id()==ID_union); + PRECONDITION(type.id() == ID_union); } /*******************************************************************\ @@ -49,10 +48,12 @@ Function: union_abstract_objectt::union_abstract_objectt \*******************************************************************/ union_abstract_objectt::union_abstract_objectt( - const typet &type, bool top, bool bottom): - abstract_objectt(type, top, bottom) + const typet &type, + bool top, + bool bottom) + : abstract_objectt(type, top, bottom) { - PRECONDITION(type.id()==ID_union); + PRECONDITION(type.id() == ID_union); } /*******************************************************************\ @@ -70,11 +71,12 @@ Function: union_abstract_objectt::union_abstract_objectt \*******************************************************************/ union_abstract_objectt::union_abstract_objectt( - const exprt &expr, const abstract_environmentt &environment, - const namespacet &ns): - abstract_objectt(expr, environment, ns) + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns) + : abstract_objectt(expr, environment, ns) { - PRECONDITION(ns.follow(expr.type()).id()==ID_union); + PRECONDITION(ns.follow(expr.type()).id() == ID_union); } /** diff --git a/src/analyses/variable-sensitivity/union_abstract_object.h b/src/analyses/variable-sensitivity/union_abstract_object.h index 9d5659ec76a..9ec22d28aab 100644 --- a/src/analyses/variable-sensitivity/union_abstract_object.h +++ b/src/analyses/variable-sensitivity/union_abstract_object.h @@ -9,21 +9,21 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_UNION_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_UNION_ABSTRACT_OBJECT_H -#include #include +#include class abstract_environmentt; class member_exprt; -class union_abstract_objectt:public abstract_objectt +class union_abstract_objectt : public abstract_objectt { public: - explicit union_abstract_objectt(const typet &type); - union_abstract_objectt(const typet &type, bool top, bool bottom); - explicit union_abstract_objectt( - const exprt &expr, - const abstract_environmentt &environment, - const namespacet &ns); + explicit union_abstract_objectt(const typet &type); + union_abstract_objectt(const typet &type, bool top, bool bottom); + explicit union_abstract_objectt( + const exprt &expr, + const abstract_environmentt &environment, + const namespacet &ns); virtual abstract_object_pointert read( const abstract_environmentt &env, @@ -39,21 +39,20 @@ class union_abstract_objectt:public abstract_objectt bool merging_write) const override; protected: - CLONE - - // union interface - virtual abstract_object_pointert read_component( - const abstract_environmentt &environment, - const member_exprt &member_expr, - const namespacet &ns) const; - - 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) const; + CLONE + + // union interface + virtual abstract_object_pointert read_component( + const abstract_environmentt &environment, + const member_exprt &member_expr, + const namespacet &ns) const; + + 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) const; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_UNION_ABSTRACT_OBJECT_H - diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index 62a2fcf284c..b7366024dd0 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -6,15 +6,14 @@ \*******************************************************************/ -#include "data_dependency_context.h" #include "variable_sensitivity_dependence_graph.h" +#include "data_dependency_context.h" +#include #include #include -#include #include - /** * Evaluate an expression and accumulate all the data dependencies * involved in the evaluation. @@ -24,16 +23,18 @@ * \param deps the destination in which to accumlate data dependencies */ void variable_sensitivity_dependence_domaint::eval_data_deps( - const exprt &expr, const namespacet &ns, data_depst &deps) const + const exprt &expr, + const namespacet &ns, + data_depst &deps) const { - const auto res= + const auto res = std::dynamic_pointer_cast(eval(expr, ns)); if(res->get_data_dependencies().size() > 0) { // If the expression was able to be eval'ed to something with data // dependencies, then that's all we need to gather. - for (const auto dep : res->get_data_dependencies()) + for(const auto dep : res->get_data_dependencies()) deps[dep].insert(expr); } else @@ -68,14 +69,14 @@ void variable_sensitivity_dependence_domaint::transform( const irep_idt &function_to, locationt to, ai_baset &ai, - const namespacet &ns) + const namespacet &ns) { variable_sensitivity_domaint::transform( function_from, from, function_to, to, ai, ns); - variable_sensitivity_dependence_grapht *dep_graph= - dynamic_cast(&ai); - assert(dep_graph!=nullptr); + variable_sensitivity_dependence_grapht *dep_graph = + dynamic_cast(&ai); + assert(dep_graph != nullptr); // propagate control dependencies across function calls if(from->is_function_call()) @@ -89,15 +90,15 @@ void variable_sensitivity_dependence_domaint::transform( // edge to function entry point const goto_programt::const_targett next = std::next(from); - variable_sensitivity_dependence_domaint *s= - dynamic_cast - (&(dep_graph->get_state(next))); - assert(s!=nullptr); + variable_sensitivity_dependence_domaint *s = + dynamic_cast( + &(dep_graph->get_state(next))); + assert(s != nullptr); if(s->has_values.is_false()) { - s->has_values=tvt::unknown(); - s->has_changed=true; + s->has_values = tvt::unknown(); + s->has_changed = true; } // modify abstract state of return location @@ -106,7 +107,7 @@ void variable_sensitivity_dependence_domaint::transform( control_dep_candidates, control_dep_calls, control_dep_call_candidates)) - s->has_changed=true; + s->has_changed = true; control_deps.clear(); control_dep_candidates.clear(); @@ -136,28 +137,28 @@ void variable_sensitivity_dependence_domaint::data_dependencies( if(to->is_assign()) { const code_assignt &inst = to_code_assign(to->code); - const exprt &rhs=inst.rhs(); + const exprt &rhs = inst.rhs(); // Handle return value of a 'no body' function if(rhs.id() == ID_side_effect) { - const side_effect_exprt &see=to_side_effect_expr(rhs); - if(see.get_statement()==ID_nondet) + const side_effect_exprt &see = to_side_effect_expr(rhs); + if(see.get_statement() == ID_nondet) { if(from->is_function_call()) { - const code_function_callt &cfc=to_code_function_call(from->code); - const exprt &call=cfc.function(); + const code_function_callt &cfc = to_code_function_call(from->code); + const exprt &call = cfc.function(); - if(call.id()==ID_symbol) + if(call.id() == ID_symbol) { - const irep_idt id=to_symbol_expr(call).id(); - const goto_functionst &goto_functions=dep_graph.goto_functions; + const irep_idt id = to_symbol_expr(call).id(); + const goto_functionst &goto_functions = dep_graph.goto_functions; - goto_functionst::function_mapt::const_iterator it= + goto_functionst::function_mapt::const_iterator it = goto_functions.function_map.find(id); - if(it!=goto_functions.function_map.end()) + if(it != goto_functions.function_map.end()) { if(!it->second.body_available()) // body not available { @@ -182,16 +183,16 @@ void variable_sensitivity_dependence_domaint::data_dependencies( eval_data_deps(rhs, ns, domain_data_deps); } } - else if (to->is_function_call()) + else if(to->is_function_call()) { const code_function_callt &call = to_code_function_call(to->code); - const code_function_callt::argumentst &args= call.arguments(); + const code_function_callt::argumentst &args = call.arguments(); for(const auto arg : args) { eval_data_deps(arg, ns, domain_data_deps); } } - else if (to->is_goto()) + else if(to->is_goto()) { eval_data_deps(to->guard, ns, domain_data_deps); } @@ -230,25 +231,25 @@ void variable_sensitivity_dependence_domaint::control_dependencies( // Compute postdominators if needed - const goto_functionst &goto_functions=dep_graph.goto_functions; + const goto_functionst &goto_functions = dep_graph.goto_functions; const irep_idt id = from_function; - cfg_post_dominatorst &pd_tmp=dep_graph.cfg_post_dominators()[id]; + cfg_post_dominatorst &pd_tmp = dep_graph.cfg_post_dominators()[id]; - goto_functionst::function_mapt::const_iterator f_it= + goto_functionst::function_mapt::const_iterator f_it = goto_functions.function_map.find(id); - if(f_it==goto_functions.function_map.end()) + if(f_it == goto_functions.function_map.end()) return; - const goto_programt &goto_program=f_it->second.body; + const goto_programt &goto_program = f_it->second.body; - if(pd_tmp.cfg.size()==0) // have we computed the dominators already? + if(pd_tmp.cfg.size() == 0) // have we computed the dominators already? { pd_tmp(goto_program); } - const cfg_post_dominatorst &pd=pd_tmp; + const cfg_post_dominatorst &pd = pd_tmp; // Check all candidates @@ -256,24 +257,22 @@ void variable_sensitivity_dependence_domaint::control_dependencies( { // check all CFG successors of M // special case: assumptions also introduce a control dependency - bool post_dom_all=!cd->is_assume(); - bool post_dom_one=false; + bool post_dom_all = !cd->is_assume(); + bool post_dom_one = false; // we could hard-code assume and goto handling here to improve // performance - const cfg_post_dominatorst::cfgt::nodet &m= - pd.get_node(cd); + const cfg_post_dominatorst::cfgt::nodet &m = pd.get_node(cd); // successors of M for(const auto &edge : m.out) { - const cfg_post_dominatorst::cfgt::nodet &m_s= - pd.cfg[edge.first]; + const cfg_post_dominatorst::cfgt::nodet &m_s = pd.cfg[edge.first]; - if(m_s.dominators.find(to)!=m_s.dominators.end()) - post_dom_one=true; + if(m_s.dominators.find(to) != m_s.dominators.end()) + post_dom_one = true; else - post_dom_all=false; + post_dom_all = false; } if(post_dom_all || !post_dom_one) @@ -282,12 +281,13 @@ void variable_sensitivity_dependence_domaint::control_dependencies( } else { - tvt branch=tvt::unknown(); + tvt branch = tvt::unknown(); if(cd->is_goto() && !cd->is_backwards_goto()) { - goto_programt::const_targett t=cd->get_target(); - branch=to->location_number>=t->location_number?tvt(false):tvt(true); + goto_programt::const_targett t = cd->get_target(); + branch = + to->location_number >= t->location_number ? tvt(false) : tvt(true); } control_deps.insert(std::make_pair(cd, branch)); @@ -314,37 +314,37 @@ bool variable_sensitivity_dependence_domaint::merge_control_dependencies( const control_dep_callst &other_control_dep_calls, const control_dep_callst &other_control_dep_call_candidates) { - bool changed=false; + bool changed = false; // Merge control dependencies - control_depst::iterator it=control_deps.begin(); + control_depst::iterator it = control_deps.begin(); for(const auto &c_dep : other_control_deps) { // find position to insert - while(it!=control_deps.end() && it->firstfirst < c_dep.first) ++it; - if(it==control_deps.end() || c_dep.firstfirst) + if(it == control_deps.end() || c_dep.first < it->first) { // hint points at position that will follow the new element control_deps.insert(it, c_dep); - changed=true; + changed = true; } else { - assert(it!=control_deps.end()); - assert(!(it->firstfirst)); + assert(it != control_deps.end()); + assert(!(it->first < c_dep.first)); + assert(!(c_dep.first < it->first)); - tvt &branch1=it->second; - const tvt &branch2=c_dep.second; + tvt &branch1 = it->second; + const tvt &branch2 = c_dep.second; - if(branch1!=branch2 && !branch1.is_unknown()) + if(branch1 != branch2 && !branch1.is_unknown()) { - branch1=tvt::unknown(); - changed=true; + branch1 = tvt::unknown(); + changed = true; } ++it; @@ -353,33 +353,31 @@ bool variable_sensitivity_dependence_domaint::merge_control_dependencies( // Merge control dependency candidates - size_t n=control_dep_candidates.size(); + size_t n = control_dep_candidates.size(); control_dep_candidates.insert( - other_control_dep_candidates.begin(), - other_control_dep_candidates.end()); + other_control_dep_candidates.begin(), other_control_dep_candidates.end()); - changed|=n!=control_dep_candidates.size(); + changed |= n != control_dep_candidates.size(); // Merge call control dependencies - n=control_dep_calls.size(); + n = control_dep_calls.size(); control_dep_calls.insert( - other_control_dep_calls.begin(), - other_control_dep_calls.end()); + other_control_dep_calls.begin(), other_control_dep_calls.end()); - changed|=n!=control_dep_calls.size(); + changed |= n != control_dep_calls.size(); // Merge call control dependency candidates - n=control_dep_call_candidates.size(); + n = control_dep_call_candidates.size(); control_dep_call_candidates.insert( - other_control_dep_call_candidates.begin(), - other_control_dep_call_candidates.end()); + other_control_dep_call_candidates.begin(), + other_control_dep_call_candidates.end()); - changed|=n!=control_dep_call_candidates.size(); + changed |= n != control_dep_call_candidates.size(); return changed; } @@ -393,9 +391,9 @@ bool variable_sensitivity_dependence_domaint::merge_control_dependencies( * \return true if something has changed in the merge */ bool variable_sensitivity_dependence_domaint::merge( - const variable_sensitivity_domaint &b, - locationt from, - locationt to) + const variable_sensitivity_domaint &b, + locationt from, + locationt to) { bool changed = false; @@ -403,11 +401,11 @@ bool variable_sensitivity_dependence_domaint::merge( changed |= has_values.is_false() || has_changed; // Handle data dependencies - const auto& cast_b = - dynamic_cast(b); + const auto &cast_b = + dynamic_cast(b); // Merge data dependencies - for (auto bdep : cast_b.domain_data_deps) + for(auto bdep : cast_b.domain_data_deps) { for(exprt bexpr : bdep.second) { @@ -422,8 +420,8 @@ bool variable_sensitivity_dependence_domaint::merge( cast_b.control_dep_calls, cast_b.control_dep_call_candidates); - has_changed=false; - has_values=tvt::unknown(); + has_changed = false; + has_values = tvt::unknown(); return changed; } @@ -453,10 +451,7 @@ void variable_sensitivity_dependence_domaint::merge_three_way_function_return( // the three way merge is that the underlying variable sensitivity domain // does its three way merge. variable_sensitivity_domaint::merge_three_way_function_return( - function_call, - function_start, - function_end, - ns); + function_call, function_start, function_end, ns); } /** @@ -467,33 +462,31 @@ void variable_sensitivity_dependence_domaint::merge_three_way_function_return( * \param ns the namespace */ void variable_sensitivity_dependence_domaint::output( - std::ostream &out, - const ai_baset &ai, - const namespacet &ns) const + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const { if(!control_deps.empty() || !control_dep_calls.empty()) { out << "Control dependencies: "; - for(control_depst::const_iterator - it=control_deps.begin(); - it!=control_deps.end(); + for(control_depst::const_iterator it = control_deps.begin(); + it != control_deps.end(); ++it) { - if(it!=control_deps.begin()) + if(it != control_deps.begin()) out << ","; - const goto_programt::const_targett cd=it->first; - const tvt branch=it->second; + const goto_programt::const_targett cd = it->first; + const tvt branch = it->second; out << cd->location_number << " [" << branch << "]"; } - for(control_dep_callst::const_iterator - it=control_dep_calls.begin(); - it!=control_dep_calls.end(); + for(control_dep_callst::const_iterator it = control_dep_calls.begin(); + it != control_dep_calls.end(); ++it) { - if(!control_deps.empty() || it!=control_dep_calls.begin()) + if(!control_deps.empty() || it != control_dep_calls.begin()) out << ","; out << (*it)->location_number << " [UNCONDITIONAL]"; @@ -504,30 +497,30 @@ void variable_sensitivity_dependence_domaint::output( if(!domain_data_deps.empty()) { - out << "Data dependencies: "; - bool first = true; - for (auto &dep : domain_data_deps) + out << "Data dependencies: "; + bool first = true; + for(auto &dep : domain_data_deps) + { + if(!first) + out << ", "; + + out << dep.first->location_number; + out << " ["; + bool first_expr = true; + for(auto &expr : dep.second) { - if(!first) + if(!first_expr) out << ", "; - out << dep.first->location_number; - out << " ["; - bool first_expr = true; - for (auto &expr : dep.second) - { - if (!first_expr) - out << ", "; - - out << from_expr(ns, "", expr); - first_expr = false; - } - out << "]"; - - first = false; + out << from_expr(ns, "", expr); + first_expr = false; } - out << std::endl; + out << "]"; + + first = false; } + out << std::endl; + } } /** @@ -546,45 +539,45 @@ jsont variable_sensitivity_dependence_domaint::output_json( for(const auto &cd : control_deps) { - const goto_programt::const_targett target=cd.first; - const tvt branch=cd.second; + const goto_programt::const_targett target = cd.first; + const tvt branch = cd.second; - json_objectt &link=graph.push_back().make_object(); + json_objectt &link = graph.push_back().make_object(); - link["locationNumber"]= + link["locationNumber"] = json_numbert(std::to_string(target->location_number)); - link["sourceLocation"]=json(target->source_location); - link["type"]=json_stringt("control"); - link["branch"]=json_stringt(branch.to_string()); + link["sourceLocation"] = json(target->source_location); + link["type"] = json_stringt("control"); + link["branch"] = json_stringt(branch.to_string()); } for(const auto &target : control_dep_calls) { - json_objectt &link=graph.push_back().make_object(); - link["locationNumber"]= + json_objectt &link = graph.push_back().make_object(); + link["locationNumber"] = json_numbert(std::to_string(target->location_number)); - link["sourceLocation"]=json(target->source_location); - link["type"]=json_stringt("control"); - link["branch"]=json_stringt("UNCONDITIONAL"); + link["sourceLocation"] = json(target->source_location); + link["type"] = json_stringt("control"); + link["branch"] = json_stringt("UNCONDITIONAL"); } for(const auto &dep : domain_data_deps) { - json_objectt &link=graph.push_back().make_object(); - link["locationNumber"]= + json_objectt &link = graph.push_back().make_object(); + link["locationNumber"] = json_numbert(std::to_string(dep.first->location_number)); - link["sourceLocation"]=json(dep.first->source_location); + link["sourceLocation"] = json(dep.first->source_location); json_stringt(dep.first->source_location.as_string()); - link["type"]=json_stringt("data"); + link["type"] = json_stringt("data"); - const std::set &expr_set=dep.second; - json_arrayt &expressions=link["expressions"].make_array(); + const std::set &expr_set = dep.second; + json_arrayt &expressions = link["expressions"].make_array(); for(const exprt &e : expr_set) { - json_objectt &object=expressions.push_back().make_object(); - object["expression"]=json_stringt(from_expr(ns, "", e)); - object["certainty"]=json_stringt("maybe"); + json_objectt &object = expressions.push_back().make_object(); + object["expression"] = json_stringt(from_expr(ns, "", e)); + object["certainty"] = json_stringt("maybe"); } } @@ -610,10 +603,10 @@ void variable_sensitivity_dependence_grapht::add_dep( goto_programt::const_targett from, goto_programt::const_targett to) { - const node_indext n_from=state_map[from].get_node_id(); - assert(n_from -#include #include +#include #include @@ -21,22 +21,28 @@ class variable_sensitivity_dependence_grapht; class vs_dep_edget { public: - enum class kindt { NONE, CTRL, DATA, BOTH }; + enum class kindt + { + NONE, + CTRL, + DATA, + BOTH + }; void add(kindt _kind) { switch(kind) { - case kindt::NONE: - kind=_kind; - break; - case kindt::DATA: - case kindt::CTRL: - if(kind!=_kind) - kind=kindt::BOTH; - break; - case kindt::BOTH: - break; + case kindt::NONE: + kind = _kind; + break; + case kindt::DATA: + case kindt::CTRL: + if(kind != _kind) + kind = kindt::BOTH; + break; + case kindt::BOTH: + break; } } @@ -49,7 +55,7 @@ class vs_dep_edget kindt kind; }; -struct vs_dep_nodet:public graph_nodet +struct vs_dep_nodet : public graph_nodet { typedef graph_nodet::edget edget; typedef graph_nodet::edgest edgest; @@ -57,17 +63,18 @@ struct vs_dep_nodet:public graph_nodet goto_programt::const_targett PC; }; -class variable_sensitivity_dependence_domaint: - public variable_sensitivity_domaint +class variable_sensitivity_dependence_domaint + : public variable_sensitivity_domaint { public: typedef grapht::node_indext node_indext; - explicit variable_sensitivity_dependence_domaint(): - node_id(std::numeric_limits::max()), - has_values(false), - has_changed(false) - {} + explicit variable_sensitivity_dependence_domaint() + : node_id(std::numeric_limits::max()), + has_values(false), + has_changed(false) + { + } void transform( const irep_idt &function_from, @@ -127,15 +134,10 @@ class variable_sensitivity_dependence_domaint: const ai_domain_baset &function_end, const namespacet &ns) override; + void output(std::ostream &out, const ai_baset &ai, const namespacet &ns) + const override; - void output( - std::ostream &out, - const ai_baset &ai, - const namespacet &ns) const override; - - jsont output_json( - const ai_baset &ai, - const namespacet &ns) const override; + jsont output_json(const ai_baset &ai, const namespacet &ns) const override; void populate_dep_graph( variable_sensitivity_dependence_grapht &, @@ -143,12 +145,12 @@ class variable_sensitivity_dependence_domaint: void set_node_id(node_indext id) { - node_id=id; + node_id = id; } node_indext get_node_id() const { - assert(node_id!=std::numeric_limits::max()); + assert(node_id != std::numeric_limits::max()); return node_id; } @@ -167,9 +169,9 @@ class variable_sensitivity_dependence_domaint: return a->location_number < b->location_number; } }; - typedef std::map< - goto_programt::const_targett, - std::set, dependency_ordert> data_depst; + typedef std:: + map, dependency_ordert> + data_depst; data_depst domain_data_deps; typedef std::map control_depst; @@ -182,8 +184,8 @@ class variable_sensitivity_dependence_domaint: control_dep_callst control_dep_calls; control_dep_callst control_dep_call_candidates; - void eval_data_deps( - const exprt &expr, const namespacet &ns, data_depst &deps) const; + void eval_data_deps(const exprt &expr, const namespacet &ns, data_depst &deps) + const; void control_dependencies( const irep_idt &from_function, @@ -205,9 +207,9 @@ class variable_sensitivity_dependence_domaint: const control_dep_callst &other_control_dep_call_candidates); }; -class variable_sensitivity_dependence_grapht: - public ait, - public grapht +class variable_sensitivity_dependence_grapht + : public ait, + public grapht { public: using ait::operator[]; @@ -242,8 +244,6 @@ class variable_sensitivity_dependence_grapht: } } - - void add_dep( vs_dep_edget::kindt kind, goto_programt::const_targett from, @@ -251,15 +251,14 @@ class variable_sensitivity_dependence_grapht: virtual statet &get_state(goto_programt::const_targett l) { - std::pair entry= - state_map.insert( - std::make_pair(l, variable_sensitivity_dependence_domaint())); + std::pair entry = state_map.insert( + std::make_pair(l, variable_sensitivity_dependence_domaint())); if(entry.second) { - const node_indext node_id=add_node(); + const node_indext node_id = add_node(); entry.first->second.set_node_id(node_id); - nodes[node_id].PC=l; + nodes[node_id].PC = l; } return entry.first->second; diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index e102c191460..9a97d7ec951 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -10,18 +10,17 @@ Date: April 2016 #include +#include #include #include -#include #include "variable_sensitivity_domain.h" #include #ifdef DEBUG -#include +# include #endif - /*******************************************************************\ Function: variable_sensitivity_domaint::transform @@ -36,85 +35,86 @@ Function: variable_sensitivity_domaint::transform \*******************************************************************/ void variable_sensitivity_domaint::transform( - const irep_idt &function_from, - locationt from, - const irep_idt &function_to, - locationt to, - ai_baset &ai, - const namespacet &ns) + const irep_idt &function_from, + locationt from, + const irep_idt &function_to, + locationt to, + ai_baset &ai, + const namespacet &ns) { - #ifdef DEBUG +#ifdef DEBUG std::cout << "Transform from/to:\n"; - std::cout << from->location_number << " --> " - << to->location_number << std::endl; - #endif + std::cout << from->location_number << " --> " << to->location_number + << std::endl; +#endif - const goto_programt::instructiont &instruction=*from; + const goto_programt::instructiont &instruction = *from; switch(instruction.type) { case DECL: - { - const abstract_objectt::locationst write_location={ from }; - abstract_object_pointert top_object= - abstract_state.abstract_object_factory( - to_code_decl(instruction.code).symbol().type(), ns, true) - ->update_location_context(write_location, true); - abstract_state.assign( - to_code_decl(instruction.code).symbol(), top_object, ns); - } - // We now store top. - break; + { + const abstract_objectt::locationst write_location = {from}; + abstract_object_pointert top_object = + abstract_state + .abstract_object_factory( + to_code_decl(instruction.code).symbol().type(), ns, true) + ->update_location_context(write_location, true); + abstract_state.assign( + to_code_decl(instruction.code).symbol(), top_object, ns); + } + // We now store top. + break; case DEAD: + { + // Remove symbol from map, the only time this occurs now (keep TOP.) + // It should be the case that DEAD only provides symbols for deletion. + const exprt &expr = to_code_dead(instruction.code).symbol(); + if(expr.id() == ID_symbol) { - // Remove symbol from map, the only time this occurs now (keep TOP.) - // It should be the case that DEAD only provides symbols for deletion. - const exprt &expr=to_code_dead(instruction.code).symbol(); - if(expr.id()==ID_symbol) - { - abstract_state.erase(to_symbol_expr(expr)); - } + abstract_state.erase(to_symbol_expr(expr)); } - break; + } + break; case ASSIGN: - { - // TODO : check return values - const code_assignt &inst = to_code_assign(instruction.code); - const abstract_objectt::locationst write_location = {from}; - abstract_object_pointert rhs = - abstract_state.eval(inst.rhs(), ns) - ->update_location_context(write_location, true); - abstract_state.assign(inst.lhs(), rhs, ns); - } - break; + { + // TODO : check return values + const code_assignt &inst = to_code_assign(instruction.code); + const abstract_objectt::locationst write_location = {from}; + abstract_object_pointert rhs = + abstract_state.eval(inst.rhs(), ns) + ->update_location_context(write_location, true); + abstract_state.assign(inst.lhs(), rhs, ns); + } + break; case GOTO: + { + if(1) // (flow_sensitivity == FLOW_SENSITIVE) { - if(1) // (flow_sensitivity == FLOW_SENSITIVE) + // Get the next line + locationt next = from; + next++; + // Is this a GOTO to the next line (i.e. pointless) + if(next != from->get_target()) { - // Get the next line - locationt next=from; - next++; - // Is this a GOTO to the next line (i.e. pointless) - if(next!=from->get_target()) + if(to == 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); - } + // 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 } + // ignore jumps to the next line, we can assume nothing } - break; + } + break; case ASSUME: abstract_state.assume(instruction.guard, ns); @@ -131,9 +131,9 @@ void variable_sensitivity_domaint::transform( // erase parameters const irep_idt id = function_from; - const symbolt &symbol=ns.lookup(id); + const symbolt &symbol = ns.lookup(id); - const code_typet &type=to_code_type(symbol.type); + const code_typet &type = to_code_type(symbol.type); for(const auto ¶m : type.parameters()) { @@ -144,7 +144,6 @@ void variable_sensitivity_domaint::transform( ns); } - break; } @@ -176,8 +175,8 @@ void variable_sensitivity_domaint::transform( throw "exceptions not handled"; case OTHER: -// throw "other"; - break; + // throw "other"; + break; case NO_INSTRUCTION_TYPE: break; @@ -243,7 +242,6 @@ void variable_sensitivity_domaint::make_top() abstract_state.make_top(); } - /*******************************************************************\ Function: variable_sensitivity_domaint::make_entry @@ -278,14 +276,13 @@ bool variable_sensitivity_domaint::merge( locationt from, locationt to) { - #ifdef DEBUG - std::cout << "Merging from/to:\n " - << from->location_number << " --> " +#ifdef DEBUG + std::cout << "Merging from/to:\n " << from->location_number << " --> " << to->location_number << std::endl; - #endif +#endif // Use the abstract_environment merge - bool any_changes=abstract_state.merge(b.abstract_state); + bool any_changes = abstract_state.merge(b.abstract_state); DATA_INVARIANT(abstract_state.verify(), "Structural invariant"); return any_changes; @@ -309,27 +306,28 @@ Function: variable_sensitivity_domaint::ai_simplify \*******************************************************************/ bool variable_sensitivity_domaint::ai_simplify( - exprt &condition, const namespacet &ns) const + exprt &condition, + const namespacet &ns) const { - 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) + if(c.id() == ID_nil) { - bool no_simplification=true; + bool no_simplification = true; // Try to simplify recursively any child operations for(exprt &op : condition.operands()) { - no_simplification&=ai_simplify(op, ns); + no_simplification &= ai_simplify(op, ns); } return no_simplification; } else { - bool condition_changed=(condition!=c); - condition=c; + bool condition_changed = (condition != c); + condition = c; return !condition_changed; } } @@ -370,9 +368,8 @@ bool variable_sensitivity_domaint::is_top() const /// Get symbols that have been modified since this domain and other /// \param other: The domain that things may have been modified in /// \return A list of symbols whose write location is different -std::vector - variable_sensitivity_domaint::get_modified_symbols( - const variable_sensitivity_domaint &other) const +std::vector variable_sensitivity_domaint::get_modified_symbols( + const variable_sensitivity_domaint &other) const { return abstract_environmentt::modified_symbols( abstract_state, other.abstract_state); @@ -400,22 +397,25 @@ Function: variable_sensitivity_domaint::transform_function_call \*******************************************************************/ void variable_sensitivity_domaint::transform_function_call( - locationt from, locationt to, ai_baset &ai, const namespacet &ns) + locationt from, + locationt to, + ai_baset &ai, + const namespacet &ns) { - PRECONDITION(from->type==FUNCTION_CALL); + PRECONDITION(from->type == FUNCTION_CALL); - const code_function_callt &function_call=to_code_function_call(from->code); - const exprt &function=function_call.function(); + const code_function_callt &function_call = to_code_function_call(from->code); + const exprt &function = function_call.function(); - const locationt next=std::next(from); + const locationt next = std::next(from); - if(function.id()==ID_symbol) + if(function.id() == ID_symbol) { // called function identifier - const symbol_exprt &symbol_expr=to_symbol_expr(function); - const irep_idt function_id=symbol_expr.get_identifier(); + const symbol_exprt &symbol_expr = to_symbol_expr(function); + const irep_idt function_id = symbol_expr.get_identifier(); - const code_function_callt::argumentst &called_arguments= + const code_function_callt::argumentst &called_arguments = function_call.arguments(); if(is_same_code_location(to, next)) @@ -439,7 +439,7 @@ void variable_sensitivity_domaint::transform_function_call( called_arg.type().id() == ID_pointer && !called_arg.type().subtype().get_bool(ID_C_constant)) { - abstract_object_pointert pointer_value= + abstract_object_pointert pointer_value = abstract_state.eval(called_arg, ns); CHECK_RETURN(pointer_value); @@ -451,7 +451,8 @@ void variable_sensitivity_domaint::transform_function_call( std::stack(), nil_exprt(), abstract_state.abstract_object_factory( - called_arg.type().subtype(), ns, true), false); + called_arg.type().subtype(), ns, true), + false); } } @@ -462,7 +463,8 @@ void variable_sensitivity_domaint::transform_function_call( { abstract_state.assign( symbol_exprt(symbol.first, symbol.second.type), - abstract_state.abstract_object_factory(symbol.second.type, ns, true), + abstract_state.abstract_object_factory( + symbol.second.type, ns, true), ns); } } @@ -471,26 +473,28 @@ void variable_sensitivity_domaint::transform_function_call( else { // we have an actual call - const symbolt &symbol=ns.lookup(function_id); - const code_typet &code_type=to_code_type(symbol.type); - const code_typet::parameterst &declaration_parameters= + const symbolt &symbol = ns.lookup(function_id); + const code_typet &code_type = to_code_type(symbol.type); + const code_typet::parameterst &declaration_parameters = code_type.parameters(); - code_typet::parameterst::const_iterator parameter_it= + code_typet::parameterst::const_iterator parameter_it = declaration_parameters.begin(); for(const exprt &called_arg : called_arguments) { - if(parameter_it==declaration_parameters.end()) + if(parameter_it == declaration_parameters.end()) { - INVARIANT(code_type.has_ellipsis(), "Only case for insufficient args"); + INVARIANT( + code_type.has_ellipsis(), "Only case for insufficient args"); break; } // Evaluate the expression that is being // passed into the function call (called_arg) - abstract_object_pointert param_val=abstract_state.eval(called_arg, ns) - ->update_location_context({from}, true); + abstract_object_pointert param_val = + abstract_state.eval(called_arg, ns) + ->update_location_context({from}, true); // Assign the evaluated value to the symbol associated with the // parameter of the function @@ -503,13 +507,13 @@ void variable_sensitivity_domaint::transform_function_call( // Too few arguments so invalid code DATA_INVARIANT( - parameter_it==declaration_parameters.end(), + parameter_it == declaration_parameters.end(), "Number of arguments should match parameters"); } } else { - PRECONDITION(to==next); + PRECONDITION(to == next); abstract_state.havoc("unknown opaque function call"); } } @@ -531,18 +535,17 @@ Function: variable_sensitivity_domaint::ignore_function_call_transform bool variable_sensitivity_domaint::ignore_function_call_transform( const irep_idt &function_id) const { - static const std::set ignored_internal_function={ + static const std::set ignored_internal_function = { CPROVER_PREFIX "set_must", CPROVER_PREFIX "get_must", CPROVER_PREFIX "set_may", CPROVER_PREFIX "get_may", CPROVER_PREFIX "cleanup", CPROVER_PREFIX "clear_may", - CPROVER_PREFIX "clear_must" - }; + CPROVER_PREFIX "clear_must"}; - return ignored_internal_function.find(function_id)!= - ignored_internal_function.cend(); + return ignored_internal_function.find(function_id) != + ignored_internal_function.cend(); } /// Perform a context aware merge of the changes that have been applied @@ -564,27 +567,27 @@ void variable_sensitivity_domaint::merge_three_way_function_return( // TODO(tkiley): flag to turn of the context aware merge if(true) { - const variable_sensitivity_domaint &cast_function_call= + const variable_sensitivity_domaint &cast_function_call = static_cast(function_call); - const variable_sensitivity_domaint &cast_function_start= + const variable_sensitivity_domaint &cast_function_start = static_cast(function_start); - const variable_sensitivity_domaint &cast_function_end= + const variable_sensitivity_domaint &cast_function_end = static_cast(function_end); const std::vector &modified_symbol_names = cast_function_start.get_modified_symbols(cast_function_end); std::vector modified_symbols; - modified_symbols.reserve(modified_symbol_names.size()); - std::transform( - modified_symbol_names.begin(), - modified_symbol_names.end(), - std::back_inserter(modified_symbols), - [&ns](const irep_idt &id) { return ns.lookup(id).symbol_expr(); }); - - abstract_state=cast_function_call.abstract_state; + modified_symbols.reserve(modified_symbol_names.size()); + std::transform( + modified_symbol_names.begin(), + modified_symbol_names.end(), + std::back_inserter(modified_symbols), + [&ns](const irep_idt &id) { return ns.lookup(id).symbol_expr(); }); + + abstract_state = cast_function_call.abstract_state; apply_domain(modified_symbols, cast_function_end, ns); } else @@ -604,9 +607,9 @@ void variable_sensitivity_domaint::apply_domain( const variable_sensitivity_domaint &source, const namespacet &ns) { - for (const auto &symbol : modified_symbols) + for(const auto &symbol : modified_symbols) { - abstract_object_pointert value=source.abstract_state.eval(symbol, ns); + abstract_object_pointert value = source.abstract_state.eval(symbol, ns); abstract_state.assign(symbol, value, ns); } } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 3f88ca4988d..64257a64596 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -62,14 +62,14 @@ into calls to eval, assume, assign and merge. #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H +#include #include #include -#include #include #include -class variable_sensitivity_domaint:public ai_domain_baset +class variable_sensitivity_domaint : public ai_domain_baset { public: virtual void transform( @@ -96,10 +96,8 @@ class variable_sensitivity_domaint:public ai_domain_baset void output(std::ostream &out) const; - virtual bool merge( - const variable_sensitivity_domaint &b, - locationt from, - locationt to); + virtual bool + merge(const variable_sensitivity_domaint &b, locationt from, locationt to); void merge_three_way_function_return( const ai_domain_baset &function_call, @@ -107,15 +105,13 @@ class variable_sensitivity_domaint:public ai_domain_baset const ai_domain_baset &function_end, const namespacet &ns) override; - bool ai_simplify( - exprt &condition, - const namespacet &ns) const override; + bool ai_simplify(exprt &condition, const namespacet &ns) const override; bool is_bottom() const override; bool is_top() const override; - virtual abstract_object_pointert eval( - const exprt &expr, const namespacet &ns) const + virtual abstract_object_pointert + eval(const exprt &expr, const namespacet &ns) const { return abstract_state.eval(expr, ns); } @@ -129,8 +125,8 @@ class variable_sensitivity_domaint:public ai_domain_baset bool ignore_function_call_transform(const irep_idt &function_id) const; - std::vector get_modified_symbols( - const variable_sensitivity_domaint &other) const; + std::vector + get_modified_symbols(const variable_sensitivity_domaint &other) const; void apply_domain( std::vector modified_symbols, diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 882e0612a3b..ae48d594ada 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -26,46 +26,45 @@ Function: variable_sensitivity_object_factoryt::get_abstract_object_type \*******************************************************************/ variable_sensitivity_object_factoryt::ABSTRACT_OBJECT_TYPET - variable_sensitivity_object_factoryt::get_abstract_object_type( - const typet type) +variable_sensitivity_object_factoryt::get_abstract_object_type(const typet type) { - ABSTRACT_OBJECT_TYPET abstract_object_type=TWO_VALUE; + ABSTRACT_OBJECT_TYPET abstract_object_type = TWO_VALUE; - if(type.id()==ID_signedbv || type.id()==ID_unsignedbv || - type.id()==ID_fixedbv || - type.id()==ID_c_bool || type.id()==ID_bool || - type.id()==ID_integer || type.id()==ID_c_bit_field) + if( + type.id() == ID_signedbv || type.id() == ID_unsignedbv || + type.id() == ID_fixedbv || type.id() == ID_c_bool || type.id() == ID_bool || + type.id() == ID_integer || type.id() == ID_c_bit_field) { abstract_object_type = configuration.advanced_sensitivities.intervals ? INTERVAL : CONSTANT; } - else if(type.id()==ID_floatbv) + else if(type.id() == ID_floatbv) { - abstract_object_type=CONSTANT; + abstract_object_type = CONSTANT; } - else if(type.id()==ID_array) + else if(type.id() == ID_array) { abstract_object_type = configuration.primitive_sensitivity.array_sensitivity ? ARRAY_SENSITIVE : ARRAY_INSENSITIVE; } - else if(type.id()==ID_pointer) + else if(type.id() == ID_pointer) { abstract_object_type = configuration.primitive_sensitivity.pointer_sensitivity ? POINTER_SENSITIVE : POINTER_INSENSITIVE; } - else if(type.id()==ID_struct) + else if(type.id() == ID_struct) { abstract_object_type = configuration.primitive_sensitivity.struct_sensitivity ? STRUCT_SENSITIVE : STRUCT_INSENSITIVE; } - else if(type.id()==ID_union) + else if(type.id() == ID_union) { - abstract_object_type=UNION_INSENSITIVE; + abstract_object_type = UNION_INSENSITIVE; } if( configuration.advanced_sensitivities.value_set && @@ -98,14 +97,14 @@ Function: variable_sensitivity_object_factoryt::get_abstract_object \*******************************************************************/ -abstract_object_pointert variable_sensitivity_object_factoryt:: - get_abstract_object( - const typet type, - bool top, - bool bottom, - const exprt &e, - const abstract_environmentt &environment, - const namespacet &ns) +abstract_object_pointert +variable_sensitivity_object_factoryt::get_abstract_object( + const typet type, + bool top, + bool bottom, + const exprt &e, + const abstract_environmentt &environment, + const namespacet &ns) { if(!initialized) { @@ -114,8 +113,8 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: "variable_sensitivity_object_factoryt::set_options()\n"; } - typet followed_type=ns.follow(type); - ABSTRACT_OBJECT_TYPET abstract_object_type= + typet followed_type = ns.follow(type); + ABSTRACT_OBJECT_TYPET abstract_object_type = get_abstract_object_type(followed_type); switch(abstract_object_type) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index a587ab71027..e3d7ca152bb 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -129,8 +129,9 @@ class variable_sensitivity_object_factoryt void set_options(const vsd_configt &options); private: - variable_sensitivity_object_factoryt():initialized(false) - {} + variable_sensitivity_object_factoryt() : initialized(false) + { + } static variable_sensitivity_object_factoryt s_instance; enum ABSTRACT_OBJECT_TYPET { @@ -188,23 +189,23 @@ Function: variable_sensitivity_object_factoryt::initialize_abstract_object \*******************************************************************/ template -abstract_object_pointert variable_sensitivity_object_factoryt:: - initialize_abstract_object( - const typet type, - bool top, - bool bottom, - const exprt &e, - const abstract_environmentt &enviroment, - const namespacet &ns) +abstract_object_pointert +variable_sensitivity_object_factoryt::initialize_abstract_object( + const typet type, + bool top, + bool bottom, + const exprt &e, + const abstract_environmentt &enviroment, + const namespacet &ns) { if(configuration.context_tracking.data_dependency_context) return initialize_context_abstract_object< - abstract_object_classt, data_dependency_contextt>( - type, top, bottom, e, enviroment, ns); + abstract_object_classt, + data_dependency_contextt>(type, top, bottom, e, enviroment, ns); if(configuration.context_tracking.last_write_context) return initialize_context_abstract_object< - abstract_object_classt, write_location_contextt>( - type, top, bottom, e, enviroment, ns); + abstract_object_classt, + write_location_contextt>(type, top, bottom, e, enviroment, ns); else { if(top || bottom) @@ -222,31 +223,31 @@ abstract_object_pointert variable_sensitivity_object_factoryt:: } template -abstract_object_pointert variable_sensitivity_object_factoryt:: - initialize_context_abstract_object( - const typet type, - bool top, - bool bottom, - const exprt &e, - const abstract_environmentt &enviroment, - const namespacet &ns) +abstract_object_pointert +variable_sensitivity_object_factoryt::initialize_context_abstract_object( + const typet type, + bool top, + bool bottom, + const exprt &e, + const abstract_environmentt &enviroment, + const namespacet &ns) { if(top || bottom) { - return abstract_object_pointert( - new context_classt( - abstract_object_pointert( - new abstract_object_classt(type, top, bottom)), - type, top, bottom)); + return abstract_object_pointert(new context_classt( + abstract_object_pointert(new abstract_object_classt(type, top, bottom)), + type, + top, + bottom)); } else { - PRECONDITION(type==ns.follow(e.type())); - return abstract_object_pointert( - new context_classt( - abstract_object_pointert( - new abstract_object_classt(e, enviroment, ns)), - e, enviroment, ns)); + PRECONDITION(type == ns.follow(e.type())); + return abstract_object_pointert(new context_classt( + abstract_object_pointert(new abstract_object_classt(e, enviroment, ns)), + e, + enviroment, + ns)); } } diff --git a/src/analyses/variable-sensitivity/write_location_context.cpp b/src/analyses/variable-sensitivity/write_location_context.cpp index e135c84b133..46c851d82a0 100644 --- a/src/analyses/variable-sensitivity/write_location_context.cpp +++ b/src/analyses/variable-sensitivity/write_location_context.cpp @@ -24,21 +24,19 @@ * \return a clone of this abstract object with it's location context * updated */ -abstract_object_pointert - write_location_contextt::update_location_context( - const abstract_objectt::locationst &locations, - const bool update_sub_elements) const +abstract_object_pointert write_location_contextt::update_location_context( + const abstract_objectt::locationst &locations, + const bool update_sub_elements) const { - const auto &result= - std::dynamic_pointer_cast( - mutable_clone()); + const auto &result = + std::dynamic_pointer_cast(mutable_clone()); if(update_sub_elements) { - abstract_object_pointert visited_child= - child_abstract_object-> - update_location_context(locations, update_sub_elements)-> - visit_sub_elements(location_update_visitort(locations)); + abstract_object_pointert visited_child = + child_abstract_object + ->update_location_context(locations, update_sub_elements) + ->visit_sub_elements(location_update_visitort(locations)); result->set_child(visited_child); } @@ -47,7 +45,7 @@ abstract_object_pointert } abstract_objectt::locationst - write_location_contextt::get_last_written_locations() const +write_location_contextt::get_last_written_locations() const { return last_written_locations; } @@ -76,9 +74,8 @@ abstract_object_pointert write_location_contextt::write( const abstract_object_pointert value, bool merging_write) const { - abstract_object_pointert updated_child= - child_abstract_object->write( - environment, ns, stack, specifier, value, merging_write); + abstract_object_pointert updated_child = child_abstract_object->write( + environment, ns, stack, specifier, value, merging_write); // Only perform an update if the write to the child has in fact changed it... if(updated_child == child_abstract_object) @@ -86,13 +83,12 @@ abstract_object_pointert write_location_contextt::write( // Need to ensure the result of the write is still wrapped in a dependency // context - const auto &result= - std::dynamic_pointer_cast( - mutable_clone()); + const auto &result = + std::dynamic_pointer_cast(mutable_clone()); // Update the child and record the updated write locations result->set_child(updated_child); - auto value_context= + auto value_context = std::dynamic_pointer_cast(value); if(value_context) @@ -113,32 +109,29 @@ abstract_object_pointert write_location_contextt::write( * \return the result of the merge, or 'this' if the merge would not change * the current abstract object */ -abstract_object_pointert write_location_contextt::merge( - abstract_object_pointert other) const +abstract_object_pointert +write_location_contextt::merge(abstract_object_pointert other) const { - auto cast_other= + auto cast_other = std::dynamic_pointer_cast(other); if(cast_other) { - bool child_modified=false; + bool child_modified = false; - auto merged_child= - abstract_objectt::merge( - child_abstract_object, cast_other->child_abstract_object, - child_modified); + auto merged_child = abstract_objectt::merge( + child_abstract_object, cast_other->child_abstract_object, child_modified); - abstract_objectt::locationst location_union=get_location_union( - cast_other->get_last_written_locations()); + abstract_objectt::locationst location_union = + get_location_union(cast_other->get_last_written_locations()); // If the union is larger than the initial set, then update. bool merge_locations = - location_union.size()>get_last_written_locations().size(); + location_union.size() > get_last_written_locations().size(); if(child_modified || merge_locations) { - const auto &result= - std::dynamic_pointer_cast( - mutable_clone()); + const auto &result = + std::dynamic_pointer_cast(mutable_clone()); if(child_modified) { result->set_child(merged_child); @@ -171,21 +164,21 @@ abstract_object_pointert write_location_contextt::merge( * \return the result of the merge */ abstract_object_pointert - write_location_contextt::abstract_object_merge_internal( - const abstract_object_pointert other) const +write_location_contextt::abstract_object_merge_internal( + const abstract_object_pointert other) const { - auto other_context= + auto other_context = std::dynamic_pointer_cast(other); if(other_context) { - abstract_objectt::locationst location_union=get_location_union( - other_context->get_last_written_locations()); + abstract_objectt::locationst location_union = + get_location_union(other_context->get_last_written_locations()); // If the union is larger than the initial set, then update. - if(location_union.size()>get_last_written_locations().size()) + if(location_union.size() > get_last_written_locations().size()) { - abstract_object_pointert result=mutable_clone(); + abstract_object_pointert result = mutable_clone(); return result->update_location_context(location_union, false); } } @@ -200,7 +193,7 @@ abstract_object_pointert void write_location_contextt::set_last_written_locations( const abstract_objectt::locationst &locations) { - last_written_locations=locations; + last_written_locations = locations; } /** @@ -212,7 +205,9 @@ void write_location_contextt::set_last_written_locations( * \param ns the current namespace */ void write_location_contextt::output( - std::ostream &out, const ai_baset &ai, const namespacet &ns) const + std::ostream &out, + const ai_baset &ai, + const namespacet &ns) const { context_abstract_objectt::output(out, ai, ns); @@ -230,10 +225,9 @@ void write_location_contextt::output( * \return the union of this objects location set, and 'locations' */ abstract_objectt::locationst - write_location_contextt::get_location_union( - const locationst &locations) const +write_location_contextt::get_location_union(const locationst &locations) const { - locationst existing_locations=get_last_written_locations(); + locationst existing_locations = get_last_written_locations(); existing_locations.insert(locations.begin(), locations.end()); return existing_locations; @@ -252,15 +246,14 @@ abstract_objectt::locationst bool write_location_contextt::has_been_modified( const abstract_object_pointert before) const { - if(this==before.get()) + if(this == before.get()) { // copy-on-write means pointer equality implies no modifications return false; } - auto before_context= - std::dynamic_pointer_cast - (before); + auto before_context = + std::dynamic_pointer_cast(before); if(!before_context) { @@ -278,9 +271,9 @@ bool write_location_contextt::has_been_modified( // For two sets of last written locations to match, // each location in one set must be equal to precisely one location // in the other, since a set can assume at most one match - const abstract_objectt::locationst &first_write_locations= + const abstract_objectt::locationst &first_write_locations = before_context->get_last_written_locations(); - const abstract_objectt::locationst &second_write_locations= + const abstract_objectt::locationst &second_write_locations = get_last_written_locations(); class location_ordert @@ -290,8 +283,7 @@ bool write_location_contextt::has_been_modified( goto_programt::const_targett instruction, goto_programt::const_targett other_instruction) const { - return instruction->location_number> - other_instruction->location_number; + return instruction->location_number > other_instruction->location_number; } }; @@ -318,8 +310,8 @@ bool write_location_contextt::has_been_modified( rhs_location.cend(), std::inserter(intersection, intersection.end()), location_ordert()); - bool all_matched=intersection.size()==first_write_locations.size() && - intersection.size()==second_write_locations.size(); + bool all_matched = intersection.size() == first_write_locations.size() && + intersection.size() == second_write_locations.size(); return !all_matched; } @@ -335,7 +327,7 @@ void write_location_contextt::output_last_written_locations( const abstract_objectt::locationst &locations) { out << "["; - bool comma=false; + bool comma = false; std::set sorted_locations; for(auto location : locations) @@ -348,7 +340,7 @@ void write_location_contextt::output_last_written_locations( if(!comma) { out << location_number; - comma=true; + comma = true; } else { diff --git a/src/analyses/variable-sensitivity/write_location_context.h b/src/analyses/variable-sensitivity/write_location_context.h index 1c861960c7f..d29c1a5fd6b 100644 --- a/src/analyses/variable-sensitivity/write_location_context.h +++ b/src/analyses/variable-sensitivity/write_location_context.h @@ -16,9 +16,9 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_LOCATION_CONTEXT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_LOCATION_CONTEXT_H -#include #include #include +#include /** * General implementation of an abstract_objectt which tracks the @@ -31,34 +31,42 @@ * of this, 'context_abstract_objectt' which provides the same * constructors as the standard 'abstract_objectt' class. */ -class write_location_contextt: public context_abstract_objectt +class write_location_contextt : public context_abstract_objectt { public: explicit write_location_contextt( const abstract_object_pointert child, - const typet &type): - context_abstract_objectt(child, type) { } + const typet &type) + : context_abstract_objectt(child, type) + { + } write_location_contextt( const abstract_object_pointert child, const typet &type, bool top, - bool bottom): - context_abstract_objectt(child, type, top, bottom) { } + bool bottom) + : context_abstract_objectt(child, type, top, bottom) + { + } explicit write_location_contextt( const abstract_object_pointert child, const exprt &expr, const abstract_environmentt &environment, - const namespacet &ns): - context_abstract_objectt(child, expr, environment, ns) { } + const namespacet &ns) + : context_abstract_objectt(child, expr, environment, ns) + { + } - virtual ~write_location_contextt() {} + virtual ~write_location_contextt() + { + } // Standard abstract_objectt interface - virtual bool has_been_modified(const abstract_object_pointert before) const - override; + virtual bool + has_been_modified(const abstract_object_pointert before) const override; virtual abstract_object_pointert update_location_context( const abstract_objectt::locationst &locations, @@ -66,12 +74,14 @@ class write_location_contextt: public context_abstract_objectt // A visitor class to update the last_written_locations of any visited // abstract_object with a given set of locations. - class location_update_visitort: - public abstract_objectt::abstract_object_visitort + class location_update_visitort + : public abstract_objectt::abstract_object_visitort { public: - explicit location_update_visitort(const locationst &locations): - locations(locations) { } + explicit location_update_visitort(const locationst &locations) + : locations(locations) + { + } abstract_object_pointert visit(const abstract_object_pointert element) const { @@ -85,15 +95,15 @@ class write_location_contextt: public context_abstract_objectt locationst get_location_union(const locationst &locations) const; virtual void output( - std::ostream &out, const class ai_baset &ai, const namespacet &ns) const - override; - + std::ostream &out, + const class ai_baset &ai, + const namespacet &ns) const override; protected: CLONE - virtual abstract_object_pointert merge( - abstract_object_pointert other) const override; + virtual abstract_object_pointert + merge(abstract_object_pointert other) const override; virtual abstract_object_pointert abstract_object_merge_internal( const abstract_object_pointert other) const override; @@ -116,8 +126,8 @@ class write_location_contextt: public context_abstract_objectt // To enforce copy-on-write these are private and have read-only accessors abstract_objectt::locationst last_written_locations; - void set_last_written_locations( - const abstract_objectt::locationst &locations); + void + set_last_written_locations(const abstract_objectt::locationst &locations); }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_LOCATION_CONTEXT_H diff --git a/src/analyses/variable-sensitivity/write_stack.cpp b/src/analyses/variable-sensitivity/write_stack.cpp index 82dcc3a1282..20028c69b83 100644 --- a/src/analyses/variable-sensitivity/write_stack.cpp +++ b/src/analyses/variable-sensitivity/write_stack.cpp @@ -16,14 +16,13 @@ #include #include -#include #include +#include /// Build a topstack -write_stackt::write_stackt(): - stack(), - top_stack(true) -{} +write_stackt::write_stackt() : stack(), top_stack(true) +{ +} /// Construct a write stack from an expression /// \param expr: The expression to represent @@ -34,16 +33,16 @@ write_stackt::write_stackt( const abstract_environmentt &environment, const namespacet &ns) { - top_stack=false; - if(expr.type().id()==ID_array) + top_stack = false; + if(expr.type().id() == ID_array) { // We are assigning an array to a pointer, which is equivalent to assigning // the first element of that arary // &(expr)[0] construct_stack_to_pointer( - address_of_exprt( - index_exprt( - expr, from_integer(0, size_type()))), environment, ns); + address_of_exprt(index_exprt(expr, from_integer(0, size_type()))), + environment, + ns); } else { @@ -60,36 +59,36 @@ void write_stackt::construct_stack_to_pointer( const abstract_environmentt &environment, const namespacet &ns) { - PRECONDITION(expr.type().id()==ID_pointer); + PRECONDITION(expr.type().id() == ID_pointer); - if(expr.id()==ID_address_of) + if(expr.id() == ID_address_of) { // resovle reminder, can either be a symbol, member or index of // otherwise unsupported construct_stack_to_lvalue(expr.op0(), environment, ns); } - else if(expr.id()==ID_plus || expr.id()==ID_minus) + else if(expr.id() == ID_plus || expr.id() == ID_minus) { exprt base; exprt offset; - const integral_resultt &which_side= + const integral_resultt &which_side = get_which_side_integral(expr, base, offset); INVARIANT( - which_side!=integral_resultt::NEITHER_INTEGRAL, + which_side != integral_resultt::NEITHER_INTEGRAL, "An offset must be an integral amount"); - if(expr.id()==ID_minus) + if(expr.id() == ID_minus) { // can't get a valid pointer by subtracting from a constant number - if(which_side==integral_resultt::LHS_INTEGRAL) + if(which_side == integral_resultt::LHS_INTEGRAL) { - top_stack=true; + top_stack = true; return; } offset = unary_minus_exprt(offset); } - abstract_object_pointert offset_value=environment.eval(offset, ns); + abstract_object_pointert offset_value = environment.eval(offset, ns); add_to_stack( std::make_shared(offset_value), environment, ns); @@ -100,21 +99,21 @@ void write_stackt::construct_stack_to_pointer( if(!top_stack) { // check the symbol at the bottom of the stack - std::shared_ptr entry=*stack.cbegin(); + std::shared_ptr entry = *stack.cbegin(); INVARIANT( - entry->get_access_expr().id()==ID_symbol, + entry->get_access_expr().id() == ID_symbol, "The base should be an addressable location (i.e. symbol)"); - if(entry->get_access_expr().type().id()!=ID_array) + if(entry->get_access_expr().type().id() != ID_array) { - top_stack=true; + top_stack = true; } } } else { // unknown expression type - play it safe and set to top - top_stack=true; + top_stack = true; } } @@ -130,22 +129,22 @@ void write_stackt::construct_stack_to_lvalue( { if(!top_stack) { - if(expr.id()==ID_member) + if(expr.id() == ID_member) { add_to_stack(std::make_shared(expr), environment, ns); construct_stack_to_lvalue(expr.op0(), environment, ns); } - else if(expr.id()==ID_symbol) + else if(expr.id() == ID_symbol) { add_to_stack(std::make_shared(expr), environment, ns); } - else if(expr.id()==ID_index) + else if(expr.id() == ID_index) { construct_stack_to_array_index(to_index_expr(expr), environment, ns); } else { - top_stack=true; + top_stack = true; } } } @@ -159,7 +158,7 @@ void write_stackt::construct_stack_to_array_index( const abstract_environmentt &environment, const namespacet &ns) { - abstract_object_pointert offset_value= + abstract_object_pointert offset_value = environment.eval(index_expr.index(), ns); add_to_stack(std::make_shared(offset_value), environment, ns); @@ -173,26 +172,26 @@ exprt write_stackt::to_expression() const { // A top stack is useless and its expression should not be evaluated PRECONDITION(!is_top_value()); - exprt access_expr=nil_exprt(); + exprt access_expr = nil_exprt(); for(const std::shared_ptr &entry : stack) { - exprt new_expr=entry->get_access_expr(); - if(access_expr.id()==ID_nil) + exprt new_expr = entry->get_access_expr(); + if(access_expr.id() == ID_nil) { - access_expr=new_expr; + access_expr = new_expr; } else { - if(new_expr.operands().size()==0) + if(new_expr.operands().size() == 0) { new_expr.operands().resize(1); } - new_expr.op0()=access_expr; + new_expr.op0() = access_expr; // If neccesary, complete the type of the new access expression entry->adjust_access_type(new_expr); - access_expr=new_expr; + access_expr = new_expr; } } address_of_exprt top_expr(access_expr); @@ -217,7 +216,8 @@ void write_stackt::add_to_stack( const abstract_environmentt environment, const namespacet &ns) { - if(stack.empty() || + if( + stack.empty() || !stack.front()->try_squash_in(entry_pointer, environment, ns)) { stack.insert(stack.begin(), entry_pointer); @@ -231,25 +231,24 @@ void write_stackt::add_to_stack( /// \param [out] out_integral_expr: The subexpression which is integraled typed. /// \return: An enum specifying whether the integral type is the LHS (op0), /// RHS (op1) or neither. -write_stackt::integral_resultt - write_stackt::get_which_side_integral( +write_stackt::integral_resultt write_stackt::get_which_side_integral( const exprt &expr, exprt &out_base_expr, exprt &out_integral_expr) { - PRECONDITION(expr.operands().size()==2); - static const std::unordered_set integral_types= - { ID_signedbv, ID_unsignedbv, ID_integer }; - if(integral_types.find(expr.op0().type().id())!=integral_types.cend()) + PRECONDITION(expr.operands().size() == 2); + static const std::unordered_set integral_types = { + ID_signedbv, ID_unsignedbv, ID_integer}; + if(integral_types.find(expr.op0().type().id()) != integral_types.cend()) { - out_integral_expr=expr.op0(); - out_base_expr=expr.op1(); + out_integral_expr = expr.op0(); + out_base_expr = expr.op1(); return integral_resultt::LHS_INTEGRAL; } - else if(integral_types.find(expr.op1().type().id())!=integral_types.cend()) + else if(integral_types.find(expr.op1().type().id()) != integral_types.cend()) { - out_integral_expr=expr.op1(); - out_base_expr=expr.op0(); + out_integral_expr = expr.op1(); + out_base_expr = expr.op0(); return integral_resultt::RHS_INTEGRAL; } else diff --git a/src/analyses/variable-sensitivity/write_stack.h b/src/analyses/variable-sensitivity/write_stack.h index f06983dbcd0..6b365346c5d 100644 --- a/src/analyses/variable-sensitivity/write_stack.h +++ b/src/analyses/variable-sensitivity/write_stack.h @@ -52,7 +52,12 @@ class write_stackt const abstract_environmentt environment, const namespacet &ns); - enum class integral_resultt { LHS_INTEGRAL, RHS_INTEGRAL, NEITHER_INTEGRAL }; + enum class integral_resultt + { + LHS_INTEGRAL, + RHS_INTEGRAL, + NEITHER_INTEGRAL + }; static integral_resultt get_which_side_integral( const exprt &expr, diff --git a/src/analyses/variable-sensitivity/write_stack_entry.cpp b/src/analyses/variable-sensitivity/write_stack_entry.cpp index 8e65def0c3d..2a1cb8a7008 100644 --- a/src/analyses/variable-sensitivity/write_stack_entry.cpp +++ b/src/analyses/variable-sensitivity/write_stack_entry.cpp @@ -30,11 +30,10 @@ bool write_stack_entryt::try_squash_in( /// Build a simple entry based off a single expression /// \param expr: The expression being represented -simple_entryt::simple_entryt(exprt expr): - simple_entry(expr) +simple_entryt::simple_entryt(exprt expr) : simple_entry(expr) { // Invalid simple expression added to the stack - PRECONDITION(expr.id()==ID_member || expr.id()==ID_symbol); + PRECONDITION(expr.id() == ID_member || expr.id() == ID_symbol); } /// Get the expression part needed to read this stack entry. For simple @@ -50,14 +49,14 @@ void simple_entryt::adjust_access_type(exprt &expr) const { } -offset_entryt::offset_entryt(abstract_object_pointert offset_value): - offset(offset_value) +offset_entryt::offset_entryt(abstract_object_pointert offset_value) + : offset(offset_value) { // The type of the abstract object should be an integral number - static const std::unordered_set integral_types= - { ID_signedbv, ID_unsignedbv, ID_integer }; + static const std::unordered_set integral_types = { + ID_signedbv, ID_unsignedbv, ID_integer}; PRECONDITION( - integral_types.find(offset_value->type().id())!=integral_types.cend()); + integral_types.find(offset_value->type().id()) != integral_types.cend()); } /// Get the expression part needed to read this stack entry. For offset entries @@ -80,7 +79,7 @@ exprt offset_entryt::get_access_expr() const void offset_entryt::adjust_access_type(exprt &expr) const { PRECONDITION(expr.id() == ID_index); - expr.type()=expr.op0().type().subtype(); + expr.type() = expr.op0().type().subtype(); } /// Try to combine a new stack element with the current top of the stack. This @@ -95,15 +94,14 @@ bool offset_entryt::try_squash_in( const abstract_environmentt &enviroment, const namespacet &ns) { - std::shared_ptr cast_entry= + std::shared_ptr cast_entry = std::dynamic_pointer_cast(new_entry); if(cast_entry) { plus_exprt result_offset( cast_entry->offset->to_constant(), offset->to_constant()); - offset=enviroment.eval(result_offset, ns); + offset = enviroment.eval(result_offset, ns); return true; } return false; } - diff --git a/src/analyses/variable-sensitivity/write_stack_entry.h b/src/analyses/variable-sensitivity/write_stack_entry.h index 60b4e6c046d..b4d8643bff5 100644 --- a/src/analyses/variable-sensitivity/write_stack_entry.h +++ b/src/analyses/variable-sensitivity/write_stack_entry.h @@ -15,16 +15,15 @@ #include #include -#include #include #include - +#include class write_stack_entryt { public: virtual ~write_stack_entryt() = default; - virtual exprt get_access_expr() const=0; + virtual exprt get_access_expr() const = 0; virtual void adjust_access_type(exprt &expr) const = 0; virtual bool try_squash_in( std::shared_ptr new_entry, @@ -32,17 +31,18 @@ class write_stack_entryt const namespacet &ns); }; -class simple_entryt:public write_stack_entryt +class simple_entryt : public write_stack_entryt { public: explicit simple_entryt(exprt expr); virtual exprt get_access_expr() const override; virtual void adjust_access_type(exprt &expr) const override; + private: exprt simple_entry; }; -class offset_entryt:public write_stack_entryt +class offset_entryt : public write_stack_entryt { public: explicit offset_entryt(abstract_object_pointert offset_value); @@ -52,9 +52,9 @@ class offset_entryt:public write_stack_entryt std::shared_ptr new_entry, const abstract_environmentt &enviroment, const namespacet &ns) override; + private: abstract_object_pointert offset; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_WRITE_STACK_ENTRY_H - diff --git a/unit/analyses/variable-sensitivity/abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp index 28da74ea945..8204a87926f 100644 --- a/unit/analyses/variable-sensitivity/abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp @@ -11,22 +11,23 @@ #include #include -SCENARIO("merge_abstract_object", +SCENARIO( + "merge_abstract_object", "[core][analyses][variable-sensitivity][abstract_object][merge]") { GIVEN("Two abstract objects of type pointer") { - const typet object_type=signedbv_typet(32); + const typet object_type = signedbv_typet(32); WHEN("Both are top") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(object_type, true, false); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(object_type, true, false); bool modifications; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modifications); THEN("The result is the original abstract object") @@ -37,20 +38,20 @@ SCENARIO("merge_abstract_object", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("The first is top, the second is bottom") { - abstract_object_pointert op1= - std::make_shared(object_type, true, false); + abstract_object_pointert op1 = + std::make_shared(object_type, true, false); - abstract_object_pointert op2= - 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); + abstract_object_pointert result = + abstract_objectt::merge(op1, op2, modifications); THEN("The result is the original abstract object") { @@ -60,19 +61,19 @@ SCENARIO("merge_abstract_object", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("The first is bottom and the second is top") { - abstract_object_pointert op1= - std::make_shared(object_type, false, true); - abstract_object_pointert op2= - std::make_shared(object_type, true, false); + abstract_object_pointert op1 = + std::make_shared(object_type, false, true); + abstract_object_pointert op2 = + std::make_shared(object_type, true, false); bool modifications; - abstract_object_pointert result= - abstract_objectt::merge(op1, op2, modifications); + abstract_object_pointert result = + abstract_objectt::merge(op1, op2, modifications); THEN("The result is top and a new abstract object") { @@ -81,19 +82,19 @@ SCENARIO("merge_abstract_object", REQUIRE(result->is_top()); REQUIRE_FALSE(result->is_bottom()); - REQUIRE_FALSE(op1==result); + REQUIRE_FALSE(op1 == result); } } 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); + 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); + abstract_object_pointert result = + abstract_objectt::merge(op1, op2, modifications); THEN("The result is the original abstract object") { @@ -103,7 +104,7 @@ SCENARIO("merge_abstract_object", REQUIRE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } } diff --git a/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp index 12b68be058d..30e73797395 100644 --- a/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp @@ -6,45 +6,46 @@ \*******************************************************************/ -#include -#include -#include -#include -#include #include #include #include +#include +#include #include #include #include +#include +#include +#include - -SCENARIO("merge_constant_abstract_value", +SCENARIO( + "merge_constant_abstract_value", "[core][analyses][variable-sensitivity][constant_abstract_value][merge]") { GIVEN("An environment with two values: 1 and 2") { - const exprt val1=from_integer(1, integer_typet()); - const exprt val2=from_integer(2, integer_typet()); + const exprt val1 = from_integer(1, integer_typet()); + const exprt val2 = from_integer(2, integer_typet()); abstract_environmentt enviroment; enviroment.make_top(); symbol_tablet symbol_table; namespacet ns(symbol_table); - WHEN("merging constant AO with value " + WHEN( + "merging constant AO with value " "with a constant AO with the same value") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1, enviroment, ns); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1, enviroment, ns); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("The original abstract object should be returned unchanged") @@ -56,25 +57,26 @@ SCENARIO("merge_constant_abstract_value", REQUIRE_FALSE(modified); REQUIRE_FALSE(cast_result->is_top()); REQUIRE_FALSE(cast_result->is_bottom()); - REQUIRE(cast_result->to_constant()==val1); + REQUIRE(cast_result->to_constant() == val1); - // Is optimal - REQUIRE(result==op1); + // Is optimal + REQUIRE(result == op1); } } - WHEN("merging constant AO with value " + WHEN( + "merging constant AO with value " "with a constant AO with the different value") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1, enviroment, ns); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val2, enviroment, ns); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("A new constant abstract object set to top should be returned") @@ -90,21 +92,21 @@ SCENARIO("merge_constant_abstract_value", // 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); - } + REQUIRE_FALSE(result == op1); + } } WHEN("merging constant AO with value with a constant AO set to top") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1, enviroment, ns); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), true, false); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("A new AO of the same type set to top ") @@ -120,21 +122,21 @@ SCENARIO("merge_constant_abstract_value", // 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); + REQUIRE_FALSE(result == op1); } } WHEN("merging constant AO with value with a constant AO set to bottom") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1, enviroment, ns); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), false, true); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("The original AO should be returned") @@ -146,22 +148,22 @@ SCENARIO("merge_constant_abstract_value", REQUIRE_FALSE(modified); REQUIRE_FALSE(cast_result->is_top()); REQUIRE_FALSE(cast_result->is_bottom()); - REQUIRE(cast_result->to_constant()==val1); + REQUIRE(cast_result->to_constant() == val1); // Is optimal - REQUIRE(result==op1); + REQUIRE(result == op1); } } WHEN("merging constant AO set to top with a constant AO with a value") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), true, false); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1, enviroment, ns); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("WE should return the same value") @@ -172,18 +174,18 @@ SCENARIO("merge_constant_abstract_value", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("merging constant AO set to top with a constant AO set to top") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), true, false); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), true, false); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("WE should return the same value") @@ -194,18 +196,18 @@ SCENARIO("merge_constant_abstract_value", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("merging constant AO set to top with a constant AO set to bottom") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), true, false); - abstract_object_pointert op2= - 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_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("WE should return the same value") @@ -216,18 +218,18 @@ SCENARIO("merge_constant_abstract_value", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("merging constant AO set to bottom with a constant AO with a value") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), false, true); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1, enviroment, ns); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("We should get an abstract object that has the same value as op2") @@ -236,18 +238,18 @@ SCENARIO("merge_constant_abstract_value", REQUIRE(modified); REQUIRE_FALSE(result->is_top()); REQUIRE_FALSE(result->is_bottom()); - REQUIRE(result->to_constant()==val1); + REQUIRE(result->to_constant() == val1); } } WHEN("merging constant AO set to bottom with a constant AO set to top") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), false, true); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), true, false); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("We should get a top abstract object back") @@ -260,13 +262,13 @@ SCENARIO("merge_constant_abstract_value", } WHEN("merging constant AO set to bottom with a constant AO set to bottom") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), false, true); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), false, true); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("We should get the same (bottom) AO back") @@ -277,21 +279,21 @@ SCENARIO("merge_constant_abstract_value", REQUIRE(result->is_bottom()); // Optimization correctness - REQUIRE(result==op1); + REQUIRE(result == op1); } } WHEN("merging constant AO with value with a abstract object set to top") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1, enviroment, ns); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), true, false); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); - const auto &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") @@ -307,21 +309,21 @@ SCENARIO("merge_constant_abstract_value", // 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); + REQUIRE_FALSE(result == op1); } } WHEN("merging constant AO with value with a abstract object set to bottom") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1, enviroment, ns); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), false, true); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("We should get the same constant AO back") { @@ -332,21 +334,21 @@ SCENARIO("merge_constant_abstract_value", REQUIRE_FALSE(modified); REQUIRE_FALSE(cast_result->is_top()); REQUIRE_FALSE(cast_result->is_bottom()); - REQUIRE(cast_result->to_constant()==val1); + REQUIRE(cast_result->to_constant() == val1); // Is optimal - REQUIRE(result==op1); + REQUIRE(result == op1); } } WHEN("merging constant AO set to top with a abstract object set to top") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), true, false); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), true, false); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("We should get the same abstract object back") @@ -357,10 +359,10 @@ SCENARIO("merge_constant_abstract_value", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); // Is type still correct - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); @@ -368,13 +370,13 @@ SCENARIO("merge_constant_abstract_value", } WHEN("merging constant AO set to top with a abstract object set to bottom") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), true, false); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), false, true); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("Should get the same abstract object back") { @@ -384,10 +386,10 @@ SCENARIO("merge_constant_abstract_value", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); // Is type still correct - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); @@ -395,13 +397,13 @@ SCENARIO("merge_constant_abstract_value", } WHEN("merging constant AO set to bottom with a abstract object set to top") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), false, true); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), true, false); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("Return a new top abstract object of the same type") { @@ -413,7 +415,7 @@ SCENARIO("merge_constant_abstract_value", // We don't optimize for returning the second parameter if we can // Is type still correct - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); @@ -421,13 +423,13 @@ SCENARIO("merge_constant_abstract_value", } WHEN("merging constant AO set to bottom with a AO set to bottom") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), false, true); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), false, true); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("Return the original abstract object") { @@ -437,10 +439,10 @@ SCENARIO("merge_constant_abstract_value", REQUIRE(result->is_bottom()); // Optimization check - REQUIRE(result==op1); + REQUIRE(result == op1); // Is type still correct - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); @@ -448,14 +450,14 @@ SCENARIO("merge_constant_abstract_value", } WHEN("merging AO set to top with a constant AO with a value") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), true, false); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1, enviroment, ns); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The original AO should be returned") { @@ -465,18 +467,18 @@ SCENARIO("merge_constant_abstract_value", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("merging AO set to top with a constant AO set to top") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), true, false); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), true, false); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The original AO should be returned") { @@ -486,18 +488,18 @@ SCENARIO("merge_constant_abstract_value", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("merging AO set to top with a constant AO set to bottom") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), true, false); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), false, true); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The original AO should be returned") { @@ -507,25 +509,25 @@ SCENARIO("merge_constant_abstract_value", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("merging AO set to bottom with a constant AO with a value") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), false, true); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1, enviroment, ns); bool modified; - abstract_object_pointert result= + 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(typeid(result.get()) == typeid(const abstract_objectt *)); REQUIRE(result->is_top()); REQUIRE_FALSE(result->is_bottom()); } @@ -534,13 +536,13 @@ SCENARIO("merge_constant_abstract_value", } WHEN("merging AO set to bottom with a constant AO set to top") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), false, true); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), true, false); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The a new top AO should be returned") @@ -555,13 +557,13 @@ SCENARIO("merge_constant_abstract_value", } WHEN("merging AO set to bottom with a constant AO set to bottom") { - abstract_object_pointert op1= + abstract_object_pointert op1 = std::make_shared(val1.type(), false, true); - abstract_object_pointert op2= + abstract_object_pointert op2 = std::make_shared(val1.type(), false, true); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The original AO should be returned") @@ -571,7 +573,7 @@ SCENARIO("merge_constant_abstract_value", REQUIRE_FALSE(result->is_top()); REQUIRE(result->is_bottom()); - REQUIRE(result==op1); + REQUIRE(result == op1); } } } 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 590f4b4b502..6b62977272f 100644 --- a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp @@ -6,12 +6,12 @@ \*******************************************************************/ -#include #include +#include #include #include -#include #include +#include #include #include @@ -28,37 +28,37 @@ typedef constant_array_abstract_objectt::constant_array_pointert // Util - class array_utilt { public: - array_utilt(const abstract_environmentt &enviroment, const namespacet &ns): - enviroment(enviroment), ns(ns) - {} + array_utilt(const abstract_environmentt &enviroment, const namespacet &ns) + : enviroment(enviroment), ns(ns) + { + } - constant_array_abstract_objectt::constant_array_pointert build_array( - const exprt &array_expr) + 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) + 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) + 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, + constant_array_abstract_object_pointert array_object, const index_exprt &index) const { return array_object->read(enviroment, index, ns)->to_constant(); @@ -69,7 +69,8 @@ class array_utilt const namespacet ns; }; -SCENARIO("merge_constant_array_abstract_object", +SCENARIO( + "merge_constant_array_abstract_object", "[core]" "[analyses][variable-sensitivity][constant_array_abstract_object][merge]") { @@ -79,23 +80,23 @@ SCENARIO("merge_constant_array_abstract_object", integer_typet(), from_integer(3, integer_typet())); // int val1[3] = {1, 2, 3} - exprt val1=array_exprt(array_type); + exprt val1 = array_exprt(array_type); val1.operands().push_back(from_integer(1, integer_typet())); val1.operands().push_back(from_integer(2, integer_typet())); val1.operands().push_back(from_integer(3, integer_typet())); // int val2[3] = {1, 4, 5} - exprt val2=array_exprt(array_type); + exprt val2 = array_exprt(array_type); val2.operands().push_back(from_integer(1, integer_typet())); val2.operands().push_back(from_integer(4, integer_typet())); val2.operands().push_back(from_integer(5, integer_typet())); // index_exprt for reading from an array - const index_exprt i0= + const index_exprt i0 = index_exprt(nil_exprt(), from_integer(0, integer_typet())); - const index_exprt i1= + const index_exprt i1 = index_exprt(nil_exprt(), from_integer(1, integer_typet())); - const index_exprt i2= + const index_exprt i2 = index_exprt(nil_exprt(), from_integer(2, integer_typet())); abstract_environmentt enviroment; @@ -109,16 +110,16 @@ SCENARIO("merge_constant_array_abstract_object", array_utilt util(enviroment, ns); abstract_object_pointert result; - bool modified=false; + 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); + 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= + const auto &cast_result = std::dynamic_pointer_cast( result); THEN("The original constant array AO should be returned") @@ -130,26 +131,27 @@ SCENARIO("merge_constant_array_abstract_object", 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()); + 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); + REQUIRE(result == op1); } } WHEN("Merging two constant array AOs with different value arrays") { - auto op1=util.build_array(val1); - auto op2=util.build_array(val2); + auto op1 = util.build_array(val1); + auto op2 = util.build_array(val2); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast( result); - THEN("A new constant array AO whose first value is the same and " + 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 @@ -159,23 +161,24 @@ SCENARIO("merge_constant_array_abstract_object", 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()); + 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); + REQUIRE_FALSE(result == op1); } } - WHEN("Merging a constant array AO with a value " + 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); + auto op1 = util.build_array(val1); + auto op2 = util.build_top_array(array_type); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast( result); THEN("A new constant array AO set to top should be returned") @@ -187,23 +190,24 @@ SCENARIO("merge_constant_array_abstract_object", 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()); + 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); + REQUIRE(result != op1); } } - WHEN("Merging a constant array AO with a value " + 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); + 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= + const auto &cast_result = std::dynamic_pointer_cast( result); THEN("The original const AO should be returned") @@ -215,23 +219,24 @@ SCENARIO("merge_constant_array_abstract_object", 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()); + 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); + REQUIRE(result == op1); } } - WHEN("Merging a constant array AO set to top " + 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); + auto op1 = util.build_top_array(array_type); + auto op2 = util.build_array(val1); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast( result); THEN("The original constant array AO should be returned") @@ -243,23 +248,24 @@ SCENARIO("merge_constant_array_abstract_object", 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()); + 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); + REQUIRE(result == op1); } } - WHEN("Merging a constant array AO set to top " + 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); + auto op1 = util.build_top_array(array_type); + auto op2 = util.build_top_array(array_type); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast( result); THEN("The original constant array AO should be returned") @@ -271,23 +277,24 @@ SCENARIO("merge_constant_array_abstract_object", 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()); + 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); + REQUIRE(result == op1); } } - WHEN("Merging a constant array AO set to top " + 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); + auto op1 = util.build_top_array(array_type); + 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= + const auto &cast_result = std::dynamic_pointer_cast( result); THEN("The original constant array AO should be returned") @@ -299,23 +306,24 @@ SCENARIO("merge_constant_array_abstract_object", 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()); + 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); + REQUIRE(result == op1); } } - WHEN("Merging a constant array AO set to bottom " + WHEN( + "Merging a constant array AO set to bottom " "with a constant array AO with a value") { - auto op1=util.build_bottom_array(array_type); - auto op2=util.build_array(val1); + auto op1 = util.build_bottom_array(array_type); + auto op2 = util.build_array(val1); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast( result); THEN("A new AO should be returned with op2s valuee") @@ -327,23 +335,24 @@ SCENARIO("merge_constant_array_abstract_object", 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()); + 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); + REQUIRE(result != op1); } } - WHEN("Merging a constant array AO set to bottom " + 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); + auto op1 = util.build_bottom_array(array_type); + auto op2 = util.build_top_array(array_type); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast( result); THEN("A new constant array AO should be returned set to top ") @@ -355,23 +364,24 @@ SCENARIO("merge_constant_array_abstract_object", 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()); + 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); + REQUIRE(result != op1); } } - WHEN("Merging a constant array AO set to bottom " + 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); + auto op1 = util.build_bottom_array(array_type); + 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= + const auto &cast_result = std::dynamic_pointer_cast( result); THEN("The original bottom AO should be returned") @@ -385,21 +395,22 @@ SCENARIO("merge_constant_array_abstract_object", REQUIRE(cast_result->is_bottom()); // Is optimal - REQUIRE(result==op1); + REQUIRE(result == op1); } } - WHEN("Merging constant array AO with value " + WHEN( + "Merging constant array AO with value " "with a abstract object set to top") { - const auto &op1=util.build_array(val1); - const auto &op2= + const auto &op1 = util.build_array(val1); + const auto &op2 = std::make_shared(val1.type(), true, false); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast( result); @@ -414,21 +425,22 @@ SCENARIO("merge_constant_array_abstract_object", REQUIRE_FALSE(cast_result->is_bottom()); // Since it has modified, we definitely shouldn't be reusing the pointer - REQUIRE_FALSE(result==op1); + REQUIRE_FALSE(result == op1); } } - WHEN("Merging constant array AO with value " + WHEN( + "Merging constant array AO with value " "with a abstract object set to bottom") { - const auto &op1=util.build_array(val1); - const auto &op2= + const auto &op1 = util.build_array(val1); + const auto &op2 = std::make_shared(val1.type(), false, true); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast( result); THEN("We should get the same constant array AO back") @@ -440,24 +452,24 @@ SCENARIO("merge_constant_array_abstract_object", 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()); + 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); + REQUIRE(result == op1); } } - WHEN("Merging constant array AO set to top " + 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= + 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_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("We should get the same abstract object back") @@ -468,26 +480,26 @@ SCENARIO("merge_constant_array_abstract_object", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); // Is type still correct - const auto &cast_result= + 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 " + 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= + 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_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("Should get the same abstract object back") { @@ -497,26 +509,26 @@ SCENARIO("merge_constant_array_abstract_object", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); // Is type still correct - const auto &cast_result= + 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") + 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= + 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_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("Return a new top abstract object of the same type") { @@ -528,7 +540,7 @@ SCENARIO("merge_constant_array_abstract_object", // We don't optimize for returning the second parameter if we can // Is type still correct - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast( result); // Though we may become top or bottom, the type should be unchanged @@ -537,13 +549,12 @@ SCENARIO("merge_constant_array_abstract_object", } 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= + 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_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("Return the original abstract object") { @@ -553,10 +564,10 @@ SCENARIO("merge_constant_array_abstract_object", REQUIRE(result->is_bottom()); // Optimization check - REQUIRE(result==op1); + REQUIRE(result == op1); // Is type still correct - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast( result); // Though we may become top or bottom, the type should be unchanged @@ -565,13 +576,13 @@ SCENARIO("merge_constant_array_abstract_object", } WHEN("Merging AO set to top with a constant array AO with a value") { - const auto &op1= + const auto &op1 = std::make_shared(val1.type(), true, false); - const auto &op2=util.build_array(val1); + const auto &op2 = util.build_array(val1); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The original AO should be returned") { @@ -581,18 +592,17 @@ SCENARIO("merge_constant_array_abstract_object", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("Merging AO set to top with a constant array AO set to top") { - const auto &op1= + const auto &op1 = std::make_shared(val1.type(), true, false); - const auto &op2= - util.build_top_array(array_type); + const auto &op2 = util.build_top_array(array_type); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The original AO should be returned") { @@ -602,18 +612,17 @@ SCENARIO("merge_constant_array_abstract_object", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("Merging AO set to top with a constant array AO set to bottom") { - const auto &op1= + const auto &op1 = std::make_shared(val1.type(), true, false); - const auto &op2= - util.build_bottom_array(array_type); + const auto &op2 = util.build_bottom_array(array_type); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The original AO should be returned") { @@ -623,24 +632,24 @@ SCENARIO("merge_constant_array_abstract_object", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("Merging AO set to bottom with a constant array AO with a value") { - const auto &op1= + const auto &op1 = std::make_shared(val1.type(), false, true); - const auto &op2=util.build_array(val1); + const auto &op2 = util.build_array(val1); bool modified; - abstract_object_pointert result= + 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(typeid(result.get()) == typeid(const abstract_objectt *)); REQUIRE(result->is_top()); REQUIRE_FALSE(result->is_bottom()); } @@ -649,13 +658,12 @@ SCENARIO("merge_constant_array_abstract_object", } WHEN("Merging AO set to bottom with a constant array AO set to top") { - const auto &op1= + const auto &op1 = std::make_shared(val1.type(), false, true); - const auto &op2= - util.build_top_array(array_type); + const auto &op2 = util.build_top_array(array_type); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The a new top AO should be returned") @@ -670,13 +678,12 @@ SCENARIO("merge_constant_array_abstract_object", } WHEN("Merging AO set to bottom with a constant array AO set to bottom") { - const auto &op1= + const auto &op1 = std::make_shared(val1.type(), false, true); - const auto &op2= - util.build_bottom_array(array_type); + const auto &op2 = util.build_bottom_array(array_type); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The original AO should be returned") @@ -686,7 +693,7 @@ SCENARIO("merge_constant_array_abstract_object", REQUIRE_FALSE(result->is_top()); REQUIRE(result->is_bottom()); - REQUIRE(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 db5dfabf80a..2d616f2bcd7 100644 --- a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp @@ -6,12 +6,12 @@ \*******************************************************************/ -#include #include +#include #include #include -#include #include +#include #include #include @@ -21,7 +21,6 @@ #include #include - #include #include #include @@ -31,47 +30,44 @@ typedef constant_array_abstract_objectt::constant_array_pointert // Util - class struct_utilt { public: - struct_utilt(abstract_environmentt &enviroment, const namespacet &ns): - enviroment(enviroment), ns(ns) - {} + 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( - enviroment, component, ns)->to_constant(); + return struct_object->read(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) + full_struct_abstract_objectt::constant_struct_pointert + build_struct(const struct_exprt &starting_value) { - std::shared_ptr result= + 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; + 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( - enviroment, - ns, - std::stack(), - member_exprt(nil_exprt(), component.get_name(), component.type()), - enviroment.eval(op, ns), - false); - result= - std::dynamic_pointer_cast( - new_result); + const auto &component = struct_type.components()[comp_index]; + std::shared_ptr new_result = result->write( + enviroment, + ns, + std::stack(), + member_exprt(nil_exprt(), component.get_name(), component.type()), + enviroment.eval(op, ns), + false); + result = std::dynamic_pointer_cast( + new_result); ++comp_index; } @@ -79,18 +75,18 @@ class struct_utilt return result; } - full_struct_abstract_objectt::constant_struct_pointert build_top_struct( - const typet &struct_type) + full_struct_abstract_objectt::constant_struct_pointert + build_top_struct(const typet &struct_type) { return std::make_shared( - struct_type, true, false); + struct_type, true, false); } - full_struct_abstract_objectt::constant_struct_pointert build_bottom_struct( - const typet &struct_type) + full_struct_abstract_objectt::constant_struct_pointert + build_bottom_struct(const typet &struct_type) { return std::make_shared( - struct_type, false, true); + struct_type, false, true); } private: @@ -98,7 +94,8 @@ class struct_utilt const namespacet ns; }; -SCENARIO("merge_full_struct_abstract_object", +SCENARIO( + "merge_full_struct_abstract_object", "[core]" "[analyses][variable-sensitivity][full_struct_abstract_object][merge]") { @@ -140,16 +137,16 @@ SCENARIO("merge_full_struct_abstract_object", struct_utilt util(enviroment, ns); abstract_object_pointert result; - bool modified=false; + 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); + auto op1 = util.build_struct(val1); + auto op2 = util.build_struct(val1); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("The original struct AO should be returned") { @@ -160,24 +157,25 @@ SCENARIO("merge_full_struct_abstract_object", 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()); + 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); + REQUIRE(result == op1); } } WHEN("Merging two constant struct AOs with the different contents") { - auto op1=util.build_struct(val1); - auto op2=util.build_struct(val2); + 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= + const auto &cast_result = std::dynamic_pointer_cast(result); - THEN("A new constant struct AO whose a component is the same and the " + 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 @@ -187,24 +185,24 @@ SCENARIO("merge_full_struct_abstract_object", 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()); - + 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); + REQUIRE_FALSE(result == op1); } } - WHEN("Merging a constant struct AO with a value " + 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); + auto op1 = util.build_struct(val1); + auto op2 = util.build_top_struct(struct_type); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("A new constant struct AO set to top should be returned") { @@ -215,23 +213,24 @@ SCENARIO("merge_full_struct_abstract_object", 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()); + 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); + REQUIRE(result != op1); } } - WHEN("Merging a constant struct AO with a value " + 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); + auto op1 = util.build_struct(val1); + auto op2 = util.build_bottom_struct(struct_type); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("The original const AO should be returned") { @@ -242,23 +241,24 @@ SCENARIO("merge_full_struct_abstract_object", 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()); + 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); + REQUIRE(result == op1); } } - WHEN("Merging a constant struct AO set to top " + 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); + auto op1 = util.build_top_struct(struct_type); + auto op2 = util.build_struct(val1); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("The original constant struct AO should be returned") { @@ -269,23 +269,24 @@ SCENARIO("merge_full_struct_abstract_object", 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()); + 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); + REQUIRE(result == op1); } } - WHEN("Merging a constant struct AO set to top " + 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); + auto op1 = util.build_top_struct(struct_type); + auto op2 = util.build_top_struct(struct_type); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("The original constant struct AO should be returned") { @@ -296,23 +297,24 @@ SCENARIO("merge_full_struct_abstract_object", 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()); + 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); + REQUIRE(result == op1); } } - WHEN("Merging a constant struct AO set to top " + 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); + auto op1 = util.build_top_struct(struct_type); + auto op2 = util.build_bottom_struct(struct_type); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("The original constant struct AO should be returned") { @@ -323,23 +325,24 @@ SCENARIO("merge_full_struct_abstract_object", 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()); + 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); + REQUIRE(result == op1); } } - WHEN("Merging a constant struct AO set to bottom " + 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); + auto op1 = util.build_bottom_struct(struct_type); + auto op2 = util.build_struct(val1); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("A new AO should be returned with op2s valuee") { @@ -350,23 +353,24 @@ SCENARIO("merge_full_struct_abstract_object", 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()); + 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); + REQUIRE(result != op1); } } - WHEN("Merging a constant struct AO set to bottom " + 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); + auto op1 = util.build_bottom_struct(struct_type); + auto op2 = util.build_top_struct(struct_type); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("A new constant struct AO should be returned set to top ") { @@ -377,23 +381,24 @@ SCENARIO("merge_full_struct_abstract_object", 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()); + 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); + REQUIRE(result != op1); } } - WHEN("Merging a constant struct AO set to bottom " + 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); + auto op1 = util.build_bottom_struct(struct_type); + auto op2 = util.build_bottom_struct(struct_type); - result=abstract_objectt::merge(op1, op2, modified); + result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("The original bottom AO should be returned") { @@ -406,21 +411,22 @@ SCENARIO("merge_full_struct_abstract_object", REQUIRE(cast_result->is_bottom()); // Is optimal - REQUIRE(result==op1); + REQUIRE(result == op1); } } - WHEN("Merging constant struct AO with value " + WHEN( + "Merging constant struct AO with value " "with a abstract object set to top") { - const auto &op1=util.build_struct(val1); - const auto &op2= + const auto &op1 = util.build_struct(val1); + const auto &op2 = std::make_shared(val1.type(), true, false); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); - const auto &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") @@ -434,21 +440,22 @@ SCENARIO("merge_full_struct_abstract_object", REQUIRE_FALSE(cast_result->is_bottom()); // Since it has modified, we definitely shouldn't be reusing the pointer - REQUIRE_FALSE(result==op1); + REQUIRE_FALSE(result == op1); } } - WHEN("Merging constant struct AO with value " + WHEN( + "Merging constant struct AO with value " "with a abstract object set to bottom") { - const auto &op1=util.build_struct(val1); - const auto &op2= + const auto &op1 = util.build_struct(val1); + const auto &op2 = std::make_shared(val1.type(), false, true); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); THEN("We should get the same constant struct AO back") { @@ -459,24 +466,24 @@ SCENARIO("merge_full_struct_abstract_object", 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()); + 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); + REQUIRE(result == op1); } } - WHEN("Merging constant struct AO set to top " + 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= + 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_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("We should get the same abstract object back") @@ -487,25 +494,25 @@ SCENARIO("merge_full_struct_abstract_object", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); // Is type still correct - const auto &cast_result= + 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 " + 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= + 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_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("Should get the same abstract object back") { @@ -515,25 +522,25 @@ SCENARIO("merge_full_struct_abstract_object", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); // Is type still correct - const auto &cast_result= + 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") + 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= + 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_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("Return a new top abstract object of the same type") { @@ -545,7 +552,7 @@ SCENARIO("merge_full_struct_abstract_object", // We don't optimize for returning the second parameter if we can // Is type still correct - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); @@ -553,13 +560,12 @@ SCENARIO("merge_full_struct_abstract_object", } 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= + 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_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("Return the original abstract object") { @@ -569,10 +575,10 @@ SCENARIO("merge_full_struct_abstract_object", REQUIRE(result->is_bottom()); // Optimization check - REQUIRE(result==op1); + REQUIRE(result == op1); // Is type still correct - const auto &cast_result= + const auto &cast_result = std::dynamic_pointer_cast(result); // Though we may become top or bottom, the type should be unchanged REQUIRE(cast_result); @@ -580,13 +586,13 @@ SCENARIO("merge_full_struct_abstract_object", } WHEN("Merging AO set to top with a constant struct AO with a value") { - const auto &op1= + const auto &op1 = std::make_shared(val1.type(), true, false); - const auto &op2=util.build_struct(val1); + const auto &op2 = util.build_struct(val1); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The original AO should be returned") { @@ -596,18 +602,17 @@ SCENARIO("merge_full_struct_abstract_object", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("Merging AO set to top with a constant struct AO set to top") { - const auto &op1= + const auto &op1 = std::make_shared(val1.type(), true, false); - const auto &op2= - util.build_top_struct(struct_type); + const auto &op2 = util.build_top_struct(struct_type); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The original AO should be returned") { @@ -617,18 +622,17 @@ SCENARIO("merge_full_struct_abstract_object", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("Merging AO set to top with a constant struct AO set to bottom") { - const auto &op1= + const auto &op1 = std::make_shared(val1.type(), true, false); - const auto &op2= - util.build_bottom_struct(struct_type); + const auto &op2 = util.build_bottom_struct(struct_type); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The original AO should be returned") { @@ -638,24 +642,24 @@ SCENARIO("merge_full_struct_abstract_object", REQUIRE_FALSE(result->is_bottom()); // Is optimal - REQUIRE(op1==result); + REQUIRE(op1 == result); } } WHEN("Merging AO set to bottom with a constant struct AO with a value") { - const auto &op1= + const auto &op1 = std::make_shared(val1.type(), false, true); - const auto &op2=util.build_struct(val1); + const auto &op2 = util.build_struct(val1); bool modified; - abstract_object_pointert result= + 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(typeid(result.get()) == typeid(const abstract_objectt *)); REQUIRE(result->is_top()); REQUIRE_FALSE(result->is_bottom()); } @@ -664,13 +668,12 @@ SCENARIO("merge_full_struct_abstract_object", } WHEN("Merging AO set to bottom with a constant struct AO set to top") { - const auto &op1= + const auto &op1 = std::make_shared(val1.type(), false, true); - const auto &op2= - util.build_top_struct(struct_type); + const auto &op2 = util.build_top_struct(struct_type); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The a new top AO should be returned") @@ -685,13 +688,12 @@ SCENARIO("merge_full_struct_abstract_object", } WHEN("Merging AO set to bottom with a constant struct AO set to bottom") { - const auto &op1= + const auto &op1 = std::make_shared(val1.type(), false, true); - const auto &op2= - util.build_bottom_struct(struct_type); + const auto &op2 = util.build_bottom_struct(struct_type); bool modified; - abstract_object_pointert result= + abstract_object_pointert result = abstract_objectt::merge(op1, op2, modified); THEN("The original AO should be returned") @@ -701,7 +703,7 @@ SCENARIO("merge_full_struct_abstract_object", REQUIRE_FALSE(result->is_top()); REQUIRE(result->is_bottom()); - REQUIRE(result==op1); + REQUIRE(result == op1); } } } diff --git a/unit/analyses/variable-sensitivity/last_written_location.cpp b/unit/analyses/variable-sensitivity/last_written_location.cpp index 94411159276..569d3278c4b 100644 --- a/unit/analyses/variable-sensitivity/last_written_location.cpp +++ b/unit/analyses/variable-sensitivity/last_written_location.cpp @@ -15,22 +15,24 @@ #include #include +#include +#include +#include #include +#include +#include #include #include #include #include -#include #include -#include -#include -#include -#include //#include -SCENARIO("Constructing two environments to make sure we correctly identify modified symbols", - "[core][analyses][variable-sensitivity][last-written-location]") +SCENARIO( + "Constructing two environments to make sure we correctly identify modified " + "symbols", + "[core][analyses][variable-sensitivity][last-written-location]") { GIVEN("Two identifiers that contain integer values") { @@ -73,9 +75,10 @@ SCENARIO("Constructing two environments to make sure we correctly identify modif second_env.assign(first_val, first_eval_rhs, ns); second_env.assign(second_val, second_eval_rhs, ns); - THEN("The modified symbols between the two domains should be none") { - auto changed_vals = abstract_environmentt::modified_symbols( - env, second_env); + THEN("The modified symbols between the two domains should be none") + { + auto changed_vals = + abstract_environmentt::modified_symbols(env, second_env); REQUIRE(changed_vals.size() == 0); } } @@ -100,7 +103,8 @@ SCENARIO("Constructing two environments to make sure we correctly identify modif symbol_table.add(second_sym); namespacet ns(symbol_table); - WHEN("The identifiers get inserted into two environments, but one of \ + WHEN( + "The identifiers get inserted into two environments, but one of \ them has a different value in one of the environments") { abstract_environmentt env; @@ -122,9 +126,10 @@ SCENARIO("Constructing two environments to make sure we correctly identify modif second_env.assign(first_val, first_eval_rhs, ns); second_env.assign(second_val, new_rhs_val, ns); - THEN("The modified symbols between the two domains should be none") { - auto changed_vals = abstract_environmentt::modified_symbols( - env, second_env); + THEN("The modified symbols between the two domains should be none") + { + auto changed_vals = + abstract_environmentt::modified_symbols(env, second_env); REQUIRE(changed_vals.size() == 0); } } From c6b69baed5431ce9c62958c7d123e70b6d06edad Mon Sep 17 00:00:00 2001 From: martin Date: Sat, 4 Jul 2020 22:23:30 +0100 Subject: [PATCH 302/342] Update test description for the move to __CPROVER_assert Somehow these changes had got lost during development. --- regression/goto-analyzer/intervals_01/test.desc | 16 ++++++++-------- regression/goto-analyzer/intervals_13/test.desc | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/regression/goto-analyzer/intervals_01/test.desc b/regression/goto-analyzer/intervals_01/test.desc index 26e34b62369..278a7b2ac97 100644 --- a/regression/goto-analyzer/intervals_01/test.desc +++ b/regression/goto-analyzer/intervals_01/test.desc @@ -3,13 +3,13 @@ main.c --intervals ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 7 assertion i\s*>=\s*10: SUCCESS$ -^\[main.assertion.2\] line 10 assertion i\s*!=\s*30: SUCCESS$ -^\[main.assertion.3\] line 13 assertion i\s*!=\s*15: UNKNOWN$ -^\[main.assertion.4\] line 16 assertion 0: SUCCESS \(unreachable\)$ -^\[main.assertion.5\] line 19 assertion j\s*>=\s*10: SUCCESS$ -^\[main.assertion.6\] line 22 assertion i\s*>=\s*j: UNKNOWN$ -^\[main.assertion.7\] line 25 assertion i\s*>=\s*11: SUCCESS$ -^\[main.assertion.8]\ line 28 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 \(unreachable\)$ +^\[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_13/test.desc b/regression/goto-analyzer/intervals_13/test.desc index 7da576c1e95..3acfeaa398e 100644 --- a/regression/goto-analyzer/intervals_13/test.desc +++ b/regression/goto-analyzer/intervals_13/test.desc @@ -3,13 +3,13 @@ main.c --intervals ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 7 assertion i\s*>=\s*10: SUCCESS$ -^\[main.assertion.2\] line 10 assertion i\s*!=\s*30: SUCCESS$ -^\[main.assertion.3\] line 13 assertion i\s*!=\s*15: UNKNOWN$ -^\[main.assertion.4\] line 16 assertion 0: SUCCESS \(unreachable\)$ -^\[main.assertion.5\] line 19 assertion j\s*>=\s*10: SUCCESS$ -^\[main.assertion.6\] line 22 assertion i\s*>=\s*j: UNKNOWN$ -^\[main.assertion.7\] line 25 assertion i\s*>=\s*11: SUCCESS$ -^\[main.assertion.8\] line 28 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 \(unreachable\)$ +^\[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 From c3482e5411434bf5d36047aa6d810b66c6226a5e Mon Sep 17 00:00:00 2001 From: martin Date: Sat, 4 Jul 2020 22:28:00 +0100 Subject: [PATCH 303/342] Rather than change existing tests, create new test descriptions A number of the tests for the old constants domain had been converted to test the variable sensitivity domain. This would reduce the test coverage of the --constants domain. So instead new .desc files have been added so both can be tested on the same input programs, allowing side-by-side comparison. --- .../goto-analyzer/constant_propagation_01/test-vsd.desc | 9 +++++++++ .../goto-analyzer/constant_propagation_01/test.desc | 2 +- .../goto-analyzer/constant_propagation_02/test-vsd.desc | 9 +++++++++ .../goto-analyzer/constant_propagation_02/test.desc | 2 +- .../goto-analyzer/constant_propagation_03/test-vsd.desc | 9 +++++++++ .../goto-analyzer/constant_propagation_03/test.desc | 2 +- .../goto-analyzer/constant_propagation_04/test-vsd.desc | 9 +++++++++ .../goto-analyzer/constant_propagation_04/test.desc | 2 +- .../goto-analyzer/constant_propagation_05/test-vsd.desc | 8 ++++++++ .../goto-analyzer/constant_propagation_05/test.desc | 2 +- .../goto-analyzer/constant_propagation_06/test-vsd.desc | 8 ++++++++ .../goto-analyzer/constant_propagation_06/test.desc | 2 +- .../goto-analyzer/constant_propagation_07/test-vsd.desc | 9 +++++++++ .../goto-analyzer/constant_propagation_07/test.desc | 2 +- .../goto-analyzer/constant_propagation_08/test-vsd.desc | 9 +++++++++ .../goto-analyzer/constant_propagation_08/test.desc | 2 +- .../goto-analyzer/constant_propagation_09/test-vsd.desc | 8 ++++++++ .../goto-analyzer/constant_propagation_09/test.desc | 2 +- .../goto-analyzer/constant_propagation_10/test-vsd.desc | 8 ++++++++ .../goto-analyzer/constant_propagation_10/test.desc | 2 +- .../goto-analyzer/constant_propagation_11/test-vsd.desc | 9 +++++++++ .../goto-analyzer/constant_propagation_11/test.desc | 2 +- .../goto-analyzer/constant_propagation_12/test-vsd.desc | 9 +++++++++ .../goto-analyzer/constant_propagation_12/test.desc | 2 +- .../goto-analyzer/constant_propagation_13/test-vsd.desc | 8 ++++++++ .../goto-analyzer/constant_propagation_13/test.desc | 2 +- .../goto-analyzer/constant_propagation_14/test-vsd.desc | 9 +++++++++ .../goto-analyzer/constant_propagation_14/test.desc | 2 +- .../goto-analyzer/constant_propagation_15/test-vsd.desc | 8 ++++++++ .../goto-analyzer/constant_propagation_15/test.desc | 2 +- .../goto-analyzer/constant_propagation_16/test-vsd.desc | 7 +++++++ .../goto-analyzer/constant_propagation_17/test-vsd.desc | 8 ++++++++ .../goto-analyzer/constant_propagation_18/test-vsd.desc | 8 ++++++++ .../goto-analyzer/constant_propagation_19/test-vsd.desc | 8 ++++++++ 34 files changed, 175 insertions(+), 15 deletions(-) create mode 100644 regression/goto-analyzer/constant_propagation_01/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_02/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_03/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_04/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_05/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_06/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_07/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_08/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_09/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_10/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_11/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_12/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_13/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_14/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_15/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_16/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_17/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_18/test-vsd.desc create mode 100644 regression/goto-analyzer/constant_propagation_19/test-vsd.desc diff --git a/regression/goto-analyzer/constant_propagation_01/test-vsd.desc b/regression/goto-analyzer/constant_propagation_01/test-vsd.desc new file mode 100644 index 00000000000..64b7bbafd9b --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_01/test-vsd.desc @@ -0,0 +1,9 @@ +CORE +main.c +--variable --simplify out.gb +^EXIT=0$ +^SIGNAL=0$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 18, function calls: 2$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_01/test.desc b/regression/goto-analyzer/constant_propagation_01/test.desc index 576370a0c05..ff04300c5c0 100644 --- a/regression/goto-analyzer/constant_propagation_01/test.desc +++ b/regression/goto-analyzer/constant_propagation_01/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --simplify out.gb +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 7, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_02/test-vsd.desc b/regression/goto-analyzer/constant_propagation_02/test-vsd.desc new file mode 100644 index 00000000000..3aadc11a5f3 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_02/test-vsd.desc @@ -0,0 +1,9 @@ +CORE +main.c +--variable --simplify out.gb +^EXIT=0$ +^SIGNAL=0$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 9, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 17, 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 4d03e2dc47f..1aed1891945 100644 --- a/regression/goto-analyzer/constant_propagation_02/test.desc +++ b/regression/goto-analyzer/constant_propagation_02/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --simplify out.gb +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_03/test-vsd.desc b/regression/goto-analyzer/constant_propagation_03/test-vsd.desc new file mode 100644 index 00000000000..3aadc11a5f3 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_03/test-vsd.desc @@ -0,0 +1,9 @@ +CORE +main.c +--variable --simplify out.gb +^EXIT=0$ +^SIGNAL=0$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 9, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 17, function calls: 2$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_03/test.desc b/regression/goto-analyzer/constant_propagation_03/test.desc index 4d03e2dc47f..1aed1891945 100644 --- a/regression/goto-analyzer/constant_propagation_03/test.desc +++ b/regression/goto-analyzer/constant_propagation_03/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --simplify out.gb +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_04/test-vsd.desc b/regression/goto-analyzer/constant_propagation_04/test-vsd.desc new file mode 100644 index 00000000000..3aadc11a5f3 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_04/test-vsd.desc @@ -0,0 +1,9 @@ +CORE +main.c +--variable --simplify out.gb +^EXIT=0$ +^SIGNAL=0$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 9, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 17, 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 4d03e2dc47f..1aed1891945 100644 --- a/regression/goto-analyzer/constant_propagation_04/test.desc +++ b/regression/goto-analyzer/constant_propagation_04/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --simplify out.gb +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_05/test-vsd.desc b/regression/goto-analyzer/constant_propagation_05/test-vsd.desc new file mode 100644 index 00000000000..f608823f827 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_05/test-vsd.desc @@ -0,0 +1,8 @@ +CORE +main.c +--variable --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main\.assertion\.1\] .* j!=3: FAILURE \(if reachable\)$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_05/test.desc b/regression/goto-analyzer/constant_propagation_05/test.desc index f608823f827..72286f84e2e 100644 --- a/regression/goto-analyzer/constant_propagation_05/test.desc +++ b/regression/goto-analyzer/constant_propagation_05/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --verify +--constants --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] .* j!=3: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_06/test-vsd.desc b/regression/goto-analyzer/constant_propagation_06/test-vsd.desc new file mode 100644 index 00000000000..ac2aec727c4 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_06/test-vsd.desc @@ -0,0 +1,8 @@ +CORE +main.c +--variable --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] .* i\s*<\s*51: UNKNOWN$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_06/test.desc b/regression/goto-analyzer/constant_propagation_06/test.desc index ac2aec727c4..dd5af473380 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 ---variable --verify +--constants --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* i\s*<\s*51: UNKNOWN$ diff --git a/regression/goto-analyzer/constant_propagation_07/test-vsd.desc b/regression/goto-analyzer/constant_propagation_07/test-vsd.desc new file mode 100644 index 00000000000..be8ad04d5a6 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_07/test-vsd.desc @@ -0,0 +1,9 @@ +KNOWNBUG +main.c +--variable --simplify out.gb +^EXIT=0$ +^SIGNAL=0$ +^Simplified: assert: 1, assume: 0, goto: 3, assigns: 14, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 15, function calls: 2$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_07/test.desc b/regression/goto-analyzer/constant_propagation_07/test.desc index e014e66bd22..0e6ee2c04ee 100644 --- a/regression/goto-analyzer/constant_propagation_07/test.desc +++ b/regression/goto-analyzer/constant_propagation_07/test.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---variable --simplify out.gb +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 3, assigns: 13, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_08/test-vsd.desc b/regression/goto-analyzer/constant_propagation_08/test-vsd.desc new file mode 100644 index 00000000000..4b10f41e952 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_08/test-vsd.desc @@ -0,0 +1,9 @@ +KNOWNBUG +main.c +--variable --arrays --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$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_08/test.desc b/regression/goto-analyzer/constant_propagation_08/test.desc index 4b10f41e952..beddc104b13 100644 --- a/regression/goto-analyzer/constant_propagation_08/test.desc +++ b/regression/goto-analyzer/constant_propagation_08/test.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---variable --arrays --simplify out.gb +--constants --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-vsd.desc b/regression/goto-analyzer/constant_propagation_09/test-vsd.desc new file mode 100644 index 00000000000..efd54ca17aa --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_09/test-vsd.desc @@ -0,0 +1,8 @@ +KNOWNBUG +main.c +--variable --arrays --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 0: FAILURE \(if reachable\)$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_09/test.desc b/regression/goto-analyzer/constant_propagation_09/test.desc index efd54ca17aa..fd4f0be0e61 100644 --- a/regression/goto-analyzer/constant_propagation_09/test.desc +++ b/regression/goto-analyzer/constant_propagation_09/test.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---variable --arrays --verify +--constants --arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 0: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_10/test-vsd.desc b/regression/goto-analyzer/constant_propagation_10/test-vsd.desc new file mode 100644 index 00000000000..fcc7a098b29 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_10/test-vsd.desc @@ -0,0 +1,8 @@ +CORE +main.c +--variable --arrays --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main\.assertion\.1\] line 10 a\[0\]==2: FAILURE \(if reachable\)$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_10/test.desc b/regression/goto-analyzer/constant_propagation_10/test.desc index fcc7a098b29..0728aedc43a 100644 --- a/regression/goto-analyzer/constant_propagation_10/test.desc +++ b/regression/goto-analyzer/constant_propagation_10/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --arrays --verify +--constants --arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] line 10 a\[0\]==2: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_11/test-vsd.desc b/regression/goto-analyzer/constant_propagation_11/test-vsd.desc new file mode 100644 index 00000000000..2c21db37186 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_11/test-vsd.desc @@ -0,0 +1,9 @@ +CORE +main.c +--variable --arrays --simplify out.gb +^EXIT=0$ +^SIGNAL=0$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 7, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 12, function calls: 2$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_11/test.desc b/regression/goto-analyzer/constant_propagation_11/test.desc index 2c21db37186..08aa42f8422 100644 --- a/regression/goto-analyzer/constant_propagation_11/test.desc +++ b/regression/goto-analyzer/constant_propagation_11/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --arrays --simplify out.gb +--constants --arrays --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 7, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_12/test-vsd.desc b/regression/goto-analyzer/constant_propagation_12/test-vsd.desc new file mode 100644 index 00000000000..de6f32ba004 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_12/test-vsd.desc @@ -0,0 +1,9 @@ +KNOWNBUG +main.c +--variable --simplify out.gb +^EXIT=0$ +^SIGNAL=0$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 16, 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 3ac7d06ccad..8900020b9b2 100644 --- a/regression/goto-analyzer/constant_propagation_12/test.desc +++ b/regression/goto-analyzer/constant_propagation_12/test.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---variable --simplify out.gb +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 7, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_13/test-vsd.desc b/regression/goto-analyzer/constant_propagation_13/test-vsd.desc new file mode 100644 index 00000000000..8ced11a1357 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_13/test-vsd.desc @@ -0,0 +1,8 @@ +CORE +main.c +--variable --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main\.assertion\.1\] .* y==0: FAILURE \(if reachable\)$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_13/test.desc b/regression/goto-analyzer/constant_propagation_13/test.desc index 8ced11a1357..5da13a53d59 100644 --- a/regression/goto-analyzer/constant_propagation_13/test.desc +++ b/regression/goto-analyzer/constant_propagation_13/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --verify +--constants --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] .* y==0: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_14/test-vsd.desc b/regression/goto-analyzer/constant_propagation_14/test-vsd.desc new file mode 100644 index 00000000000..6a3a4b25fd6 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_14/test-vsd.desc @@ -0,0 +1,9 @@ +CORE +main.c +--variable --arrays --verify +^EXIT=0$ +^SIGNAL=0$ +\[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_14/test.desc b/regression/goto-analyzer/constant_propagation_14/test.desc index 6a3a4b25fd6..374af7d45e5 100644 --- a/regression/goto-analyzer/constant_propagation_14/test.desc +++ b/regression/goto-analyzer/constant_propagation_14/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --arrays --verify +--constants --arrays --verify ^EXIT=0$ ^SIGNAL=0$ \[main\.assertion\.1\] .* a\[0\]==1 || a\[0\]==2: SUCCESS$ diff --git a/regression/goto-analyzer/constant_propagation_15/test-vsd.desc b/regression/goto-analyzer/constant_propagation_15/test-vsd.desc new file mode 100644 index 00000000000..4aafae8319e --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_15/test-vsd.desc @@ -0,0 +1,8 @@ +CORE +main.c +--variable --arrays --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main\.assertion\.1\] .* a\[0\]==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 4aafae8319e..5a2438aedc2 100644 --- a/regression/goto-analyzer/constant_propagation_15/test.desc +++ b/regression/goto-analyzer/constant_propagation_15/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --arrays --verify +--constants --arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] .* a\[0\]==2: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_16/test-vsd.desc b/regression/goto-analyzer/constant_propagation_16/test-vsd.desc new file mode 100644 index 00000000000..f2d74c835aa --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_16/test-vsd.desc @@ -0,0 +1,7 @@ +CORE +main.c +--show --variable +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_17/test-vsd.desc b/regression/goto-analyzer/constant_propagation_17/test-vsd.desc new file mode 100644 index 00000000000..a4a7c537e4a --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_17/test-vsd.desc @@ -0,0 +1,8 @@ +CORE +main.c +--variable --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main\.assertion\.1\] .* i\s*<\s*51: (UNKNOWN|FAILURE \(if reachable\))$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_18/test-vsd.desc b/regression/goto-analyzer/constant_propagation_18/test-vsd.desc new file mode 100644 index 00000000000..9a6265af079 --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_18/test-vsd.desc @@ -0,0 +1,8 @@ +CORE +main.c +--variable --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] line 7 assertion \*p == 1: SUCCESS$ +-- +^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_19/test-vsd.desc b/regression/goto-analyzer/constant_propagation_19/test-vsd.desc new file mode 100644 index 00000000000..f5f4fee881b --- /dev/null +++ b/regression/goto-analyzer/constant_propagation_19/test-vsd.desc @@ -0,0 +1,8 @@ +CORE +main.c +--variable --verify +^EXIT=0$ +^SIGNAL=0$ +^\[main.assertion.1\] line 8 assertion x == 42: SUCCESS$ +-- +^warning: ignoring From 8628e1b9e8a809382364702eed90e619d8801e17 Mon Sep 17 00:00:00 2001 From: martin Date: Sat, 4 Jul 2020 23:10:05 +0100 Subject: [PATCH 304/342] Three way merge is not being added to ai_domaint so no override --- src/analyses/variable-sensitivity/variable_sensitivity_domain.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 64257a64596..63da5ec1238 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -103,7 +103,7 @@ class variable_sensitivity_domaint : public ai_domain_baset const ai_domain_baset &function_call, const ai_domain_baset &function_start, const ai_domain_baset &function_end, - const namespacet &ns) override; + const namespacet &ns); bool ai_simplify(exprt &condition, const namespacet &ns) const override; From 73350b9fd1b14c4ea6b8588c1775fb4f558f545e Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Tue, 26 May 2020 10:10:22 +0100 Subject: [PATCH 305/342] Use brace initialisation instead of parentheses --- src/analyses/variable-sensitivity/value_set_abstract_value.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/value_set_abstract_value.cpp b/src/analyses/variable-sensitivity/value_set_abstract_value.cpp index 5d80f5a1ad2..61380daa1ce 100644 --- a/src/analyses/variable-sensitivity/value_set_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/value_set_abstract_value.cpp @@ -9,6 +9,6 @@ #include "value_set_abstract_value.h" value_set_abstract_valuet::value_set_abstract_valuet(const typet &type) - : abstract_valuet(type) + : abstract_valuet{type} { } From cdc9e2439d71fd84660880d3d4df51c34d03bd21 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Tue, 26 May 2020 15:06:10 +0100 Subject: [PATCH 306/342] Implement merge for value_set_abstract_valuet --- .../value_set_abstract_value.cpp | 66 ++++- .../value_set_abstract_value.h | 26 ++ .../value_set/abstract_value.cpp | 225 ++++++++++++++++++ .../value_set/module_dependencies.txt | 1 + 4 files changed, 317 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/value_set_abstract_value.cpp b/src/analyses/variable-sensitivity/value_set_abstract_value.cpp index 61380daa1ce..99ea4e0fd52 100644 --- a/src/analyses/variable-sensitivity/value_set_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/value_set_abstract_value.cpp @@ -9,6 +9,70 @@ #include "value_set_abstract_value.h" value_set_abstract_valuet::value_set_abstract_valuet(const typet &type) - : abstract_valuet{type} + : abstract_valuet{type}, values{} +{ +} + +const value_set_abstract_valuet::valuest & +value_set_abstract_valuet::get_values() const +{ + PRECONDITION(!is_top()); + PRECONDITION(!is_bottom()); + return values; +} + +abstract_object_pointert +value_set_abstract_valuet::merge(abstract_object_pointert other) const +{ + if(is_top()) + { + return shared_from_this(); + } + + if(other->is_top()) + { + return other; + } + + if(is_bottom()) + { + return other; + } + + if(other->is_bottom()) + { + return shared_from_this(); + } + + if( + auto other_value_set = + dynamic_cast(other.get())) + { + valuest merged_values{values}; + auto const &other_values = other_value_set->get_values(); + merged_values.insert(other_values.begin(), other_values.end()); + return std::make_shared( + type(), std::move(merged_values)); + } + return abstract_objectt::merge(other); +} + +value_set_abstract_valuet::value_set_abstract_valuet( + const typet &type, + valuest values) + : abstract_valuet{type, values.size() > max_value_set_size, values.empty()}, + values{std::move(values)} +{ + if(values.size() > max_value_set_size) + { + this->values.clear(); + } +} + +value_set_abstract_valuet::value_set_abstract_valuet( + exprt expr, + const abstract_environmentt &environment, + const namespacet &ns) + : value_set_abstract_valuet{expr.type(), valuest{expr}} { } diff --git a/src/analyses/variable-sensitivity/value_set_abstract_value.h b/src/analyses/variable-sensitivity/value_set_abstract_value.h index 91731b7e43d..f56ef055ef0 100644 --- a/src/analyses/variable-sensitivity/value_set_abstract_value.h +++ b/src/analyses/variable-sensitivity/value_set_abstract_value.h @@ -16,11 +16,37 @@ #include "abstract_value.h" +#include + class value_set_abstract_valuet : public abstract_valuet { public: + using valuest = std::unordered_set; + explicit value_set_abstract_valuet(const typet &type); + value_set_abstract_valuet( + exprt expr, + const abstract_environmentt &environment, + const namespacet &ns); + value_set_abstract_valuet(const typet &type, valuest values); + + /// Get the possible values for this abstract object. + /// Only meaningful when this is neither TOP nor BOTTOM. + const valuest &get_values() const; + CLONE + + /// TODO arbitrary limit, make configurable + static constexpr std::size_t max_value_set_size = 10; + +protected: + abstract_object_pointert merge(abstract_object_pointert other) const override; + +private: + /// If BOTTOM then empty. + /// If neither BOTTOM or TOP then the exact set of values. + /// If TOP this field doesn't mean anything and shouldn't be looked at. + valuest values; }; // NOLINTNEXTLINE(whitespace/line_length) diff --git a/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp b/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp index a2caf5344d3..25e8d79b1e5 100644 --- a/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp +++ b/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp @@ -8,6 +8,60 @@ Author: Diffblue Ltd. #include "value_set_test_common.h" #include +#include + +#include +#include +#include +#include + +namespace +{ +// NOLINTNEXTLINE(readability/identifiers) +class ContainsAllOf + : public Catch::MatcherBase +{ +private: + std::vector should_contain_values; + +public: + template + explicit ContainsAllOf(Args &&... should_contain_values) + : should_contain_values{std::forward(should_contain_values)...} + { + } + + bool match(const value_set_abstract_valuet::valuest &values) const override + { + for(auto const &value : should_contain_values) + { + if(values.count(value) == 0) + { + return false; + } + } + return true; + } + + std::string describe() const override + { + std::ostringstream oss{}; + auto const ns = namespacet{symbol_tablet{}}; + oss << "contains all of { "; + bool first = true; + for(auto const &value : should_contain_values) + { + if(!first) + { + oss << ", "; + } + oss << expr2c(value, ns); + } + oss << " }"; + return oss.str(); + } +}; +} // namespace TEST_CASE( "A value set abstract object created from type is top", @@ -17,3 +71,174 @@ TEST_CASE( REQUIRE(abstract_value.is_top()); REQUIRE(!abstract_value.is_bottom()); } + +TEST_CASE( + "A value set created from a single value represents that value", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto const value = from_integer(10, type); + auto const value_set = value_set_abstract_valuet{type, {value}}; + + REQUIRE(!value_set.is_top()); + REQUIRE(!value_set.is_bottom()); + REQUIRE(value_set.get_values().size() == 1); + REQUIRE_THAT(value_set.get_values(), ContainsAllOf{value}); +} + +TEST_CASE( + "A value set created from multiple values represents all of them", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto const value1 = from_integer(10, type); + auto const value2 = from_integer(36, type); + auto const value3 = from_integer(42, type); + auto const value_set = + value_set_abstract_valuet{type, {value1, value2, value3}}; + + REQUIRE(!value_set.is_top()); + REQUIRE(!value_set.is_bottom()); + REQUIRE(value_set.get_values().size() == 3); + REQUIRE_THAT(value_set.get_values(), ContainsAllOf(value1, value2, value3)); +} + +TEST_CASE( + "A value set created from an empty set is bottom", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto const value_set = value_set_abstract_valuet{type, {}}; + REQUIRE(!value_set.is_top()); + REQUIRE(value_set.is_bottom()); +} + +TEST_CASE( + "A value set created with too many elements is TOP", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto values = value_set_abstract_valuet::valuest{}; + for(std::size_t i = 0; i <= value_set_abstract_valuet::max_value_set_size; + ++i) + { + values.insert(from_integer(i, type)); + } + auto const value_set = value_set_abstract_valuet{type, values}; + + REQUIRE(value_set.is_top()); + REQUIRE(!value_set.is_bottom()); +} + +TEST_CASE( + "A value set created by merging two single value-value sets contains both " + "values", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto const value1 = from_integer(10, type); + auto const value2 = from_integer(42, type); + using valuest = value_set_abstract_valuet::valuest; + auto const value_set1 = + std::make_shared(type, valuest{value1}); + auto const value_set2 = + std::make_shared(type, valuest{value2}); + + bool out_modifications; + auto const merged_abstract_object = + abstract_objectt::merge(value_set1, value_set2, out_modifications); + auto const merged_value_set = + std::dynamic_pointer_cast( + merged_abstract_object); + + REQUIRE(merged_value_set != nullptr); + REQUIRE(!merged_value_set->is_top()); + REQUIRE(!merged_value_set->is_bottom()); + REQUIRE(merged_value_set->get_values().size() == 2); + REQUIRE_THAT(merged_value_set->get_values(), ContainsAllOf(value1, value2)); +} + +TEST_CASE( + "A value set created by merging two multi-value value sets contains all " + "values from both of them", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto const value1 = from_integer(10, type); + auto const value2 = from_integer(20, type); + auto const value3 = from_integer(30, type); + using valuest = value_set_abstract_valuet::valuest; + auto const value_set1 = + std::make_shared(type, valuest{value1, value2}); + auto const value_set2 = + std::make_shared(type, valuest{value2, value3}); + + bool out_modifications; + auto const merged_abstracted_object = + abstract_objectt::merge(value_set1, value_set2, out_modifications); + auto const merged_value_set = + std::dynamic_pointer_cast( + merged_abstracted_object); + + REQUIRE(merged_value_set != nullptr); + REQUIRE(!merged_value_set->is_top()); + REQUIRE(!merged_value_set->is_bottom()); + REQUIRE(merged_value_set->get_values().size() == 3); + REQUIRE_THAT( + merged_value_set->get_values(), ContainsAllOf(value1, value2, value3)); +} + +TEST_CASE( + "The result of merging two value sets is TOP if both are non-top value sets " + "and the resulting set would have too many elements", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + using valuest = value_set_abstract_valuet::valuest; + auto values = valuest{}; + for(std::size_t i = 0; i < value_set_abstract_valuet::max_value_set_size; ++i) + { + values.insert(from_integer(i, type)); + } + + auto const straw_that_broke_the_camels_back = + from_integer(value_set_abstract_valuet::max_value_set_size, type); + + auto const value_set1 = + std::make_shared(type, values); + REQUIRE(!value_set1->is_top()); + + auto const value_set2 = std::make_shared( + type, valuest{straw_that_broke_the_camels_back}); + REQUIRE(!value_set2->is_top()); + + bool out_modifications; + auto const merged_abstract_object = + abstract_objectt::merge(value_set1, value_set2, out_modifications); + auto const merged_value_set = + std::dynamic_pointer_cast( + merged_abstract_object); + + REQUIRE(merged_value_set != nullptr); + REQUIRE(merged_value_set->is_top()); + REQUIRE(!merged_value_set->is_bottom()); +} + +TEST_CASE( + "The result of merging two value sets is top if one of them is TOP", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto const value = from_integer(10, type); + using valuest = value_set_abstract_valuet::valuest; + auto const value_set1 = + std::make_shared(type, valuest{value}); + auto const value_set2 = std::make_shared(type); + + bool out_modifications; + auto const merged_abstract_object = + abstract_objectt::merge(value_set1, value_set2, out_modifications); + + REQUIRE(merged_abstract_object->is_top()); + REQUIRE(!merged_abstract_object->is_bottom()); +} diff --git a/unit/analyses/variable-sensitivity/value_set/module_dependencies.txt b/unit/analyses/variable-sensitivity/value_set/module_dependencies.txt index ac96be3c1ef..d44f66043f7 100644 --- a/unit/analyses/variable-sensitivity/value_set/module_dependencies.txt +++ b/unit/analyses/variable-sensitivity/value_set/module_dependencies.txt @@ -1,3 +1,4 @@ analyses +ansi-c testing-utils util From 195842703c768f7f15c2b2d564361ea4d016c7b1 Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Thu, 28 May 2020 10:35:10 +0100 Subject: [PATCH 307/342] Implement output for value-set abstract values --- .../module_dependencies.txt | 1 + .../value_set_abstract_value.cpp | 34 +++++++++ .../value_set_abstract_value.h | 3 + .../value_set/abstract_value.cpp | 69 +++++++++++++++++++ 4 files changed, 107 insertions(+) diff --git a/src/analyses/variable-sensitivity/module_dependencies.txt b/src/analyses/variable-sensitivity/module_dependencies.txt index 0e78852b13c..36e4dbb826a 100644 --- a/src/analyses/variable-sensitivity/module_dependencies.txt +++ b/src/analyses/variable-sensitivity/module_dependencies.txt @@ -1,4 +1,5 @@ analyses +ansi-c goto-programs langapi # should go away util diff --git a/src/analyses/variable-sensitivity/value_set_abstract_value.cpp b/src/analyses/variable-sensitivity/value_set_abstract_value.cpp index 99ea4e0fd52..f2e4a94ec5e 100644 --- a/src/analyses/variable-sensitivity/value_set_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/value_set_abstract_value.cpp @@ -8,6 +8,8 @@ #include "value_set_abstract_value.h" +#include + value_set_abstract_valuet::value_set_abstract_valuet(const typet &type) : abstract_valuet{type}, values{} { @@ -76,3 +78,35 @@ value_set_abstract_valuet::value_set_abstract_valuet( : value_set_abstract_valuet{expr.type(), valuest{expr}} { } + +void value_set_abstract_valuet::output( + std::ostream &out, + const class ai_baset &, + const namespacet &ns) const +{ + if(is_bottom()) + { + out << "BOTTOM"; + return; + } + else if(is_top()) + { + out << "TOP"; + return; + } + + std::vector vals; + for(const auto &elem : values) + { + vals.push_back(expr2c(elem, ns)); + } + + std::sort(vals.begin(), vals.end()); + + out << "{ "; + for(const auto &val : vals) + { + out << val << " "; + } + out << "}"; +} diff --git a/src/analyses/variable-sensitivity/value_set_abstract_value.h b/src/analyses/variable-sensitivity/value_set_abstract_value.h index f56ef055ef0..c604be8aa07 100644 --- a/src/analyses/variable-sensitivity/value_set_abstract_value.h +++ b/src/analyses/variable-sensitivity/value_set_abstract_value.h @@ -39,6 +39,9 @@ class value_set_abstract_valuet : public abstract_valuet /// TODO arbitrary limit, make configurable static constexpr std::size_t max_value_set_size = 10; + void output(std::ostream &out, const class ai_baset &ai, const namespacet &ns) + const override; + protected: abstract_object_pointert merge(abstract_object_pointert other) const override; diff --git a/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp b/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp index 25e8d79b1e5..a7928ce51b5 100644 --- a/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp +++ b/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp @@ -7,7 +7,9 @@ Author: Diffblue Ltd. \*******************************************************************/ #include "value_set_test_common.h" +#include #include +#include #include #include @@ -242,3 +244,70 @@ TEST_CASE( REQUIRE(merged_abstract_object->is_top()); REQUIRE(!merged_abstract_object->is_bottom()); } + +TEST_CASE( + "Make sure the output method works correctly with a value set with 0 " + "elements", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto const value_set = value_set_abstract_valuet{type, {}}; + + std::stringstream ss; + value_set.output( + ss, ait{}, namespacet{symbol_tablet{}}); + REQUIRE(ss.str() == "BOTTOM"); +} + +TEST_CASE( + "Make sure the output method works correctly with a value set with 1 element", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto const value = from_integer(10, type); + auto const value_set = value_set_abstract_valuet{type, {value}}; + + std::stringstream ss; + value_set.output( + ss, ait{}, namespacet{symbol_tablet{}}); + REQUIRE(ss.str() == "{ 10 }"); +} + +TEST_CASE( + "Make sure the output method works correctly with a value set with 3 " + "elements", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto const value1 = from_integer(10, type); + auto const value2 = from_integer(12, type); + auto const value3 = from_integer(14, type); + auto const value_set = + value_set_abstract_valuet{type, {value1, value2, value3}}; + + std::stringstream ss; + value_set.output( + ss, ait{}, namespacet{symbol_tablet{}}); + REQUIRE(ss.str() == "{ 10 12 14 }"); +} + +TEST_CASE( + "Make sure that the output method works with a TOP value set", + VALUE_SET_TEST_TAGS) +{ + // Build and ensure value set is TOP + auto const type = signedbv_typet{32}; + auto values = value_set_abstract_valuet::valuest{}; + for(std::size_t i = 0; i <= value_set_abstract_valuet::max_value_set_size; + ++i) + { + values.insert(from_integer(i, type)); + } + auto const value_set = value_set_abstract_valuet{type, values}; + REQUIRE(value_set.is_top()); + + std::stringstream ss; + value_set.output( + ss, ait{}, namespacet{symbol_tablet{}}); + REQUIRE(ss.str() == "TOP"); +} From a9326c66b4152b7664a35afb0dc44ef665cdf85b Mon Sep 17 00:00:00 2001 From: Hannes Steffenhagen Date: Thu, 28 May 2020 14:27:03 +0100 Subject: [PATCH 308/342] Implement value_set_abstract_valuet::to_constant --- .../value_set_abstract_value.cpp | 19 ++++++- .../value_set_abstract_value.h | 7 ++- .../value_set/abstract_value.cpp | 52 ++++++++++++++++++- 3 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/analyses/variable-sensitivity/value_set_abstract_value.cpp b/src/analyses/variable-sensitivity/value_set_abstract_value.cpp index f2e4a94ec5e..7007a709789 100644 --- a/src/analyses/variable-sensitivity/value_set_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/value_set_abstract_value.cpp @@ -10,8 +10,11 @@ #include -value_set_abstract_valuet::value_set_abstract_valuet(const typet &type) - : abstract_valuet{type}, values{} +value_set_abstract_valuet::value_set_abstract_valuet( + const typet &type, + bool top, + bool bottom) + : abstract_valuet{type, top, bottom}, values{} { } @@ -79,6 +82,18 @@ value_set_abstract_valuet::value_set_abstract_valuet( { } +exprt value_set_abstract_valuet::to_constant() const +{ + if(!is_top() && !is_bottom() && values.size() == 1) + { + return *values.begin(); + } + else + { + return nil_exprt{}; + } +} + void value_set_abstract_valuet::output( std::ostream &out, const class ai_baset &, diff --git a/src/analyses/variable-sensitivity/value_set_abstract_value.h b/src/analyses/variable-sensitivity/value_set_abstract_value.h index c604be8aa07..11cb98d5841 100644 --- a/src/analyses/variable-sensitivity/value_set_abstract_value.h +++ b/src/analyses/variable-sensitivity/value_set_abstract_value.h @@ -23,7 +23,10 @@ class value_set_abstract_valuet : public abstract_valuet public: using valuest = std::unordered_set; - explicit value_set_abstract_valuet(const typet &type); + explicit value_set_abstract_valuet( + const typet &type, + bool top = true, + bool bottom = false); value_set_abstract_valuet( exprt expr, const abstract_environmentt &environment, @@ -39,6 +42,8 @@ class value_set_abstract_valuet : public abstract_valuet /// TODO arbitrary limit, make configurable static constexpr std::size_t max_value_set_size = 10; + exprt to_constant() const override; + void output(std::ostream &out, const class ai_baset &ai, const namespacet &ns) const override; diff --git a/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp b/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp index a7928ce51b5..8d78e530377 100644 --- a/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp +++ b/unit/analyses/variable-sensitivity/value_set/abstract_value.cpp @@ -110,7 +110,8 @@ TEST_CASE( VALUE_SET_TEST_TAGS) { auto const type = signedbv_typet{32}; - auto const value_set = value_set_abstract_valuet{type, {}}; + auto const value_set = + value_set_abstract_valuet{type, value_set_abstract_valuet::valuest{}}; REQUIRE(!value_set.is_top()); REQUIRE(value_set.is_bottom()); } @@ -251,7 +252,8 @@ TEST_CASE( VALUE_SET_TEST_TAGS) { auto const type = signedbv_typet{32}; - auto const value_set = value_set_abstract_valuet{type, {}}; + auto const value_set = + value_set_abstract_valuet{type, value_set_abstract_valuet::valuest{}}; std::stringstream ss; value_set.output( @@ -311,3 +313,49 @@ TEST_CASE( ss, ait{}, namespacet{symbol_tablet{}}); REQUIRE(ss.str() == "TOP"); } + +TEST_CASE( + "Value set abstract value that is TOP can not be turned into a constant", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto const value_set = value_set_abstract_valuet{type}; + + REQUIRE(value_set.to_constant() == nil_exprt{}); +} + +TEST_CASE( + "Value set abstract value that is bottom can not be turned into a constant", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto const value_set = + value_set_abstract_valuet{type, value_set_abstract_valuet::valuest{}}; + + REQUIRE(value_set.to_constant() == nil_exprt{}); +} + +TEST_CASE( + "Value set with multiple possible values can not be turned into a constant", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto values = value_set_abstract_valuet::valuest{}; + values.insert(from_integer(0, type)); + values.insert(from_integer(1, type)); + auto const value_set = value_set_abstract_valuet{type, values}; + + REQUIRE(value_set.to_constant() == nil_exprt{}); +} + +TEST_CASE( + "Value set with exactly one possible value can be turned into a constant", + VALUE_SET_TEST_TAGS) +{ + auto const type = signedbv_typet{32}; + auto const value = from_integer(0, type); + auto const value_set = + value_set_abstract_valuet{type, value_set_abstract_valuet::valuest{value}}; + + REQUIRE(value_set.to_constant() == value); +} From bc8ff680ac3810999882ceffc105ad25e7cdab56 Mon Sep 17 00:00:00 2001 From: martin Date: Thu, 16 Jul 2020 10:46:01 +0100 Subject: [PATCH 309/342] Update the use of exprts so that it is more type safe --- .../abstract_enviroment.cpp | 14 ++++++++++-- .../constant_pointer_abstract_object.cpp | 7 +++--- .../interval_abstract_value.cpp | 7 +++--- .../variable-sensitivity/write_stack.cpp | 22 +++++++++++-------- .../write_stack_entry.cpp | 2 +- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index ab9cf30814d..ed308d99ddf 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -183,10 +183,20 @@ bool abstract_environmentt::assign( 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) + if(s.id() == ID_index) { stactions.push(s); - s = s.op0(); + s = to_index_expr(s).array(); + } + else if(s.id() == ID_member) + { + stactions.push(s); + s = to_member_expr(s).struct_op(); + } + else if(s.id() == ID_dereference) + { + stactions.push(s); + s = to_dereference_expr(s).pointer(); } else { diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index c147d465129..302f572bc70 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -301,7 +301,8 @@ abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( } else { - return env.eval(value_stack.to_expression().op0(), ns); + return env.eval( + to_address_of_expr(value_stack.to_expression()).object(), ns); } } @@ -351,7 +352,7 @@ constant_pointer_abstract_objectt::write_dereference( PRECONDITION(new_value->type() == ns.follow(type().subtype())); // Get an expression that we can assign to - exprt value = value_stack.to_expression().op0(); + exprt value = to_address_of_expr(value_stack.to_expression()).object(); if(merging_write) { abstract_object_pointert pointed_value = environment.eval(value, ns); @@ -367,7 +368,7 @@ constant_pointer_abstract_objectt::write_dereference( } else { - exprt value = value_stack.to_expression().op0(); + exprt value = to_address_of_expr(value_stack.to_expression()).object(); abstract_object_pointert pointed_value = environment.eval(value, ns); abstract_object_pointert modified_value = environment.write(pointed_value, new_value, stack, ns, merging_write); diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.cpp b/src/analyses/variable-sensitivity/interval_abstract_value.cpp index 391ab4f63d1..b7800c415a9 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/interval_abstract_value.cpp @@ -21,7 +21,7 @@ static inline exprt look_through_casts(exprt e) { while(e.id() == ID_typecast) { - e = e.op0(); + e = to_typecast_expr(e).op(); } return e; } @@ -145,8 +145,9 @@ static inline constant_interval_exprt interval_from_relation(const exprt &e) { PRECONDITION(e.operands().size() == 2); const auto &relation = e.id(); - const auto &lhs = e.op0(); - const auto &rhs = e.op1(); + const auto &binary_e = to_binary_expr(e); + const auto &lhs = binary_e.lhs(); + const auto &rhs = binary_e.rhs(); PRECONDITION( relation == ID_le || relation == ID_lt || relation == ID_ge || relation == ID_gt || relation == ID_equal); diff --git a/src/analyses/variable-sensitivity/write_stack.cpp b/src/analyses/variable-sensitivity/write_stack.cpp index 20028c69b83..3bbed827246 100644 --- a/src/analyses/variable-sensitivity/write_stack.cpp +++ b/src/analyses/variable-sensitivity/write_stack.cpp @@ -65,7 +65,8 @@ void write_stackt::construct_stack_to_pointer( { // resovle reminder, can either be a symbol, member or index of // otherwise unsupported - construct_stack_to_lvalue(expr.op0(), environment, ns); + construct_stack_to_lvalue( + to_address_of_expr(expr).object(), environment, ns); } else if(expr.id() == ID_plus || expr.id() == ID_minus) { @@ -132,7 +133,8 @@ void write_stackt::construct_stack_to_lvalue( if(expr.id() == ID_member) { add_to_stack(std::make_shared(expr), environment, ns); - construct_stack_to_lvalue(expr.op0(), environment, ns); + construct_stack_to_lvalue( + to_member_expr(expr).struct_op(), environment, ns); } else if(expr.id() == ID_symbol) { @@ -186,7 +188,7 @@ exprt write_stackt::to_expression() const { new_expr.operands().resize(1); } - new_expr.op0() = access_expr; + new_expr.operands()[0] = access_expr; // If neccesary, complete the type of the new access expression entry->adjust_access_type(new_expr); @@ -237,18 +239,20 @@ write_stackt::integral_resultt write_stackt::get_which_side_integral( exprt &out_integral_expr) { PRECONDITION(expr.operands().size() == 2); + const auto binary_e = to_binary_expr(expr); static const std::unordered_set integral_types = { ID_signedbv, ID_unsignedbv, ID_integer}; - if(integral_types.find(expr.op0().type().id()) != integral_types.cend()) + if(integral_types.find(binary_e.lhs().type().id()) != integral_types.cend()) { - out_integral_expr = expr.op0(); - out_base_expr = expr.op1(); + out_integral_expr = binary_e.lhs(); + out_base_expr = binary_e.rhs(); return integral_resultt::LHS_INTEGRAL; } - else if(integral_types.find(expr.op1().type().id()) != integral_types.cend()) + else if( + integral_types.find(binary_e.rhs().type().id()) != integral_types.cend()) { - out_integral_expr = expr.op1(); - out_base_expr = expr.op0(); + out_integral_expr = binary_e.rhs(); + out_base_expr = binary_e.lhs(); return integral_resultt::RHS_INTEGRAL; } else diff --git a/src/analyses/variable-sensitivity/write_stack_entry.cpp b/src/analyses/variable-sensitivity/write_stack_entry.cpp index 2a1cb8a7008..da7cfc239d4 100644 --- a/src/analyses/variable-sensitivity/write_stack_entry.cpp +++ b/src/analyses/variable-sensitivity/write_stack_entry.cpp @@ -79,7 +79,7 @@ exprt offset_entryt::get_access_expr() const void offset_entryt::adjust_access_type(exprt &expr) const { PRECONDITION(expr.id() == ID_index); - expr.type() = expr.op0().type().subtype(); + expr.type() = to_index_expr(expr).array().type().subtype(); } /// Try to combine a new stack element with the current top of the stack. This From ab7010f6e31325d822cf1661445c95a37b66b155 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 4 Aug 2020 11:01:49 +0100 Subject: [PATCH 310/342] Disable stats collection until the necessary changes are merged to ait --- .../variable-sensitivity/variable_sensitivity_domain.cpp | 3 +++ .../variable-sensitivity/variable_sensitivity_domain.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 9a97d7ec951..a7bdf6377ce 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -613,8 +613,11 @@ void variable_sensitivity_domaint::apply_domain( abstract_state.assign(symbol, value, ns); } } + +#ifdef ENABLE_STATS abstract_object_statisticst variable_sensitivity_domaint::gather_statistics(const namespacet &ns) const { return abstract_state.gather_statistics(ns); } +#endif diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 63da5ec1238..c56c7a65cc6 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -135,10 +135,13 @@ class variable_sensitivity_domaint : public ai_domain_baset abstract_environmentt abstract_state; +#ifdef ENABLE_STATS public: abstract_object_statisticst gather_statistics(const namespacet &ns) const; +#endif }; +#ifdef ENABLE_STATS template <> struct get_domain_statisticst { @@ -178,5 +181,6 @@ struct get_domain_statisticst << "<< End Variable Sensitivity Domain Statistics >>\n"; } }; +#endif #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H From a2780a5640737a0cdb7dd23529463ee5045dd5eb Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 4 Aug 2020 11:13:44 +0100 Subject: [PATCH 311/342] Replace call to a utility function that is not in the patch set --- .../variable-sensitivity/variable_sensitivity_domain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index a7bdf6377ce..0ab8d17d6a6 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -418,7 +418,7 @@ void variable_sensitivity_domaint::transform_function_call( const code_function_callt::argumentst &called_arguments = function_call.arguments(); - if(is_same_code_location(to, next)) + if(to->location_number == next->location_number) { if(ignore_function_call_transform(function_id)) { From 951f9d6f7bacd6755040e6b31d7eb35aa64d0a61 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 4 Aug 2020 11:24:05 +0100 Subject: [PATCH 312/342] Remove an unreachable fall back case ai_domain_baset::merge_three_way_function_return has been removed in favour of a simpler interface, so the call is removed. At the moment it is unreachable anyway so it is kind of a mute point. --- .../variable-sensitivity/variable_sensitivity_domain.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 0ab8d17d6a6..b9698575036 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -592,8 +592,11 @@ void variable_sensitivity_domaint::merge_three_way_function_return( } else { + UNREACHABLE; // This case is not handled but also is not currently used + /* ai_domain_baset::merge_three_way_function_return( function_call, function_start, function_end, ns); + */ } } From 9a1a1de7edd664b563be62345ee21abf476a652c Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 4 Aug 2020 11:38:42 +0100 Subject: [PATCH 313/342] Another update for the change in how three_way_merge is integrated --- src/analyses/variable-sensitivity/variable_sensitivity_domain.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index c56c7a65cc6..48efd22a344 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -99,7 +99,7 @@ class variable_sensitivity_domaint : public ai_domain_baset virtual bool merge(const variable_sensitivity_domaint &b, locationt from, locationt to); - void merge_three_way_function_return( + virtual void merge_three_way_function_return( const ai_domain_baset &function_call, const ai_domain_baset &function_start, const ai_domain_baset &function_end, From 43b8b66009d8363d1dc5d325d8f58fe4c718be27 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 4 Aug 2020 12:04:49 +0100 Subject: [PATCH 314/342] Port over some of the changes to dependence_graph to the VS version --- src/analyses/ai_storage.h | 2 ++ .../variable_sensitivity_dependence_graph.cpp | 4 ++-- .../variable_sensitivity_dependence_graph.h | 11 ++++++----- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/analyses/ai_storage.h b/src/analyses/ai_storage.h index a36b1eb146d..8880fac7e10 100644 --- a/src/analyses/ai_storage.h +++ b/src/analyses/ai_storage.h @@ -144,6 +144,7 @@ class trace_map_storaget : public ai_storage_baset // A couple of older domains make direct use of the state map class invariant_propagationt; class dependence_grapht; +class variable_sensitivity_dependence_grapht; /// The most conventional storage; one domain per location class location_sensitive_storaget : public trace_map_storaget @@ -161,6 +162,7 @@ class location_sensitive_storaget : public trace_map_storaget // Support some older domains that explicitly iterate across the state map friend invariant_propagationt; friend dependence_grapht; + friend variable_sensitivity_dependence_grapht; // Based on dependence_grapht state_mapt &internal(void) { return state_map; diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index b7366024dd0..bb387636a33 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -603,9 +603,9 @@ void variable_sensitivity_dependence_grapht::add_dep( goto_programt::const_targett from, goto_programt::const_targett to) { - const node_indext n_from = state_map[from].get_node_id(); + const node_indext n_from = (*this)[from].get_node_id(); assert(n_from < size()); - const node_indext n_to = state_map[to].get_node_id(); + const node_indext n_to = (*this)[to].get_node_id(); assert(n_to < size()); // add_edge is redundant as the subsequent operations also insert diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h index b3763f3f821..b539b5570d7 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -221,9 +221,8 @@ class variable_sensitivity_dependence_grapht explicit variable_sensitivity_dependence_grapht( const goto_functionst &goto_functions, - const namespacet &_ns, - const ai_configt &config = {}) - : ait(config), + const namespacet &_ns) + : ait(), goto_functions(goto_functions), ns(_ns) { @@ -238,9 +237,11 @@ class variable_sensitivity_dependence_grapht void finalize() { - for(const auto &location_state : state_map) + for(const auto &location_state : + static_cast(*storage).internal()) { - location_state.second.populate_dep_graph(*this, location_state.first); + std::static_pointer_cast(location_state.second) + ->populate_dep_graph(*this, location_state.first); } } From 2ca5cf798f31a5c0e67ab5541edcd407457f196d Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 4 Aug 2020 12:14:10 +0100 Subject: [PATCH 315/342] fixup the unreachable thing --- .../variable-sensitivity/variable_sensitivity_domain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index b9698575036..95ddcb460b1 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -592,7 +592,7 @@ void variable_sensitivity_domaint::merge_three_way_function_return( } else { - UNREACHABLE; // This case is not handled but also is not currently used + UNREACHABLE; // This case is not handled but also is not currently used /* ai_domain_baset::merge_three_way_function_return( function_call, function_start, function_end, ns); From 1fa8cfff9c11944c791ae1ec9ecc2be5ee9dde42 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 4 Aug 2020 12:18:54 +0100 Subject: [PATCH 316/342] Tweak the update to VSDG --- .../variable_sensitivity_dependence_graph.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h index b539b5570d7..4028678ae94 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -240,7 +240,8 @@ class variable_sensitivity_dependence_grapht for(const auto &location_state : static_cast(*storage).internal()) { - std::static_pointer_cast(location_state.second) + std::static_pointer_cast( + location_state.second) ->populate_dep_graph(*this, location_state.first); } } From c796ee05b93ce2e07c78c507888b9c59dfdbee11 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 4 Aug 2020 12:33:13 +0100 Subject: [PATCH 317/342] Refactor the VS dependency graph analysis to use the domain factory This is a direct port of 07f8696e1c8168b3e61b024841720473504a573b which use(d|s) the factory interface to build domains with a non-trivial constructor, in this case passing the location. This avoids creating invalid objects and doing the "lazy construction" in get_state. --- .../variable_sensitivity_dependence_graph.cpp | 37 +++++++++++++++++++ .../variable_sensitivity_dependence_graph.h | 37 ++++--------------- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index bb387636a33..fb5a2f89642 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -598,6 +598,43 @@ void variable_sensitivity_dependence_domaint::populate_dep_graph( dep_graph.add_dep(vs_dep_edget::kindt::DATA, d_dep.first, this_loc); } +/// This ensures that all domains are constructed with the node ID that links +/// them to the graph part of the dependency graph. Using a factory is a tad +/// verbose but it works well with the ait infrastructure. +class variable_sensitivity_dependence_domain_factoryt + : public ai_domain_factoryt +{ +public: + explicit variable_sensitivity_dependence_domain_factoryt( + variable_sensitivity_dependence_grapht &_dg) + : dg(_dg) + { + } + + std::unique_ptr make(locationt l) const override + { + auto node_id = dg.add_node(); + dg.nodes[node_id].PC = l; + auto p = util_make_unique(node_id); + CHECK_RETURN(p->is_bottom()); + + return std::unique_ptr(p.release()); + } + +private: + variable_sensitivity_dependence_grapht &dg; +}; + +variable_sensitivity_dependence_grapht::variable_sensitivity_dependence_grapht( + const goto_functionst &goto_functions, + const namespacet &_ns) + : ait( + util_make_unique(*this)), + goto_functions(goto_functions), + ns(_ns) +{ +} + void variable_sensitivity_dependence_grapht::add_dep( vs_dep_edget::kindt kind, goto_programt::const_targett from, diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h index 4028678ae94..574d8b20316 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -69,10 +69,8 @@ class variable_sensitivity_dependence_domaint public: typedef grapht::node_indext node_indext; - explicit variable_sensitivity_dependence_domaint() - : node_id(std::numeric_limits::max()), - has_values(false), - has_changed(false) + explicit variable_sensitivity_dependence_domaint(node_indext id) + : node_id(id), has_values(false), has_changed(false) { } @@ -143,11 +141,6 @@ class variable_sensitivity_dependence_domaint variable_sensitivity_dependence_grapht &, goto_programt::const_targett) const; - void set_node_id(node_indext id) - { - node_id = id; - } - node_indext get_node_id() const { assert(node_id != std::numeric_limits::max()); @@ -207,6 +200,8 @@ class variable_sensitivity_dependence_domaint const control_dep_callst &other_control_dep_call_candidates); }; +class variable_sensitivity_dependence_domain_factoryt; + class variable_sensitivity_dependence_grapht : public ait, public grapht @@ -221,12 +216,7 @@ class variable_sensitivity_dependence_grapht explicit variable_sensitivity_dependence_grapht( const goto_functionst &goto_functions, - const namespacet &_ns) - : ait(), - goto_functions(goto_functions), - ns(_ns) - { - } + const namespacet &_ns); void initialize(const irep_idt &function_id, const goto_programt &goto_program) @@ -251,27 +241,14 @@ class variable_sensitivity_dependence_grapht goto_programt::const_targett from, goto_programt::const_targett to); - virtual statet &get_state(goto_programt::const_targett l) - { - std::pair entry = state_map.insert( - std::make_pair(l, variable_sensitivity_dependence_domaint())); - - if(entry.second) - { - const node_indext node_id = add_node(); - entry.first->second.set_node_id(node_id); - nodes[node_id].PC = l; - } - - return entry.first->second; - } - post_dominators_mapt &cfg_post_dominators() { return post_dominators; } protected: + friend variable_sensitivity_dependence_domain_factoryt; + friend variable_sensitivity_dependence_domaint; const goto_functionst &goto_functions; const namespacet &ns; From 367d42608712c1412edc5eda3735d1709a04d8fb Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 4 Aug 2020 20:14:05 +0100 Subject: [PATCH 318/342] Fix all of the linting errors --- .../abstract_enviroment.cpp | 2 -- .../variable-sensitivity/abstract_object.h | 2 +- .../abstract_object_statistics.h | 8 +++++++ .../array_abstract_object.h | 4 ++-- .../constant_abstract_value.cpp | 4 ++-- .../constant_abstract_value.h | 9 ++++---- .../constant_array_abstract_object.cpp | 2 +- .../constant_array_abstract_object.h | 17 +++++++------- .../constant_pointer_abstract_object.h | 3 +-- .../context_abstract_object.h | 23 ++++++++----------- .../data_dependency_context.h | 15 +++++------- .../full_struct_abstract_object.cpp | 6 ++--- .../full_struct_abstract_object.h | 13 +++++------ .../interval_abstract_value.h | 7 +++--- .../interval_array_abstract_object.h | 6 ++--- .../pointer_abstract_object.h | 4 ++-- .../struct_abstract_object.h | 4 ++-- .../union_abstract_object.h | 4 ++-- .../variable_sensitivity_dependence_graph.cpp | 18 +++++++++------ .../variable_sensitivity_dependence_graph.h | 14 ++++++----- .../variable_sensitivity_domain.cpp | 5 ++-- .../variable_sensitivity_domain.h | 14 +++++------ .../write_location_context.h | 18 ++++++--------- .../variable-sensitivity/write_stack_entry.h | 10 ++++---- src/util/std_expr.h | 2 ++ .../abstract_object/module_dependencies.txt | 3 +++ .../module_dependencies.txt | 3 +++ .../module_dependencies.txt | 3 +++ .../module_dependencies.txt | 3 +++ .../module_dependencies.txt | 3 +++ .../last_written_location.cpp | 6 ++--- .../module_dependencies.txt | 3 +++ 32 files changed, 125 insertions(+), 113 deletions(-) create mode 100644 unit/analyses/variable-sensitivity/abstract_object/module_dependencies.txt create mode 100644 unit/analyses/variable-sensitivity/constant_abstract_value/module_dependencies.txt create mode 100644 unit/analyses/variable-sensitivity/constant_array_abstract_object/module_dependencies.txt create mode 100644 unit/analyses/variable-sensitivity/full_struct_abstract_object/module_dependencies.txt create mode 100644 unit/analyses/variable-sensitivity/interval_abstract_value/module_dependencies.txt create mode 100644 unit/analyses/variable-sensitivity/module_dependencies.txt diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index ed308d99ddf..6ad9413ffbd 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -491,8 +491,6 @@ Function: abstract_environmentt::merge \*******************************************************************/ -#include - bool abstract_environmentt::merge(const abstract_environmentt &env) { // Use the sharing_map's "iterative over all differences" functionality diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index c34fe7a4695..f1f1cb6ed23 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -43,7 +43,7 @@ class abstract_environmentt; class namespacet; #define CLONE \ - virtual internal_abstract_object_pointert mutable_clone() const override \ + internal_abstract_object_pointert mutable_clone() const override \ { \ typedef std::remove_const< \ std::remove_reference::type>::type current_typet; \ diff --git a/src/analyses/variable-sensitivity/abstract_object_statistics.h b/src/analyses/variable-sensitivity/abstract_object_statistics.h index a9dac9e653a..d2d75c2624a 100644 --- a/src/analyses/variable-sensitivity/abstract_object_statistics.h +++ b/src/analyses/variable-sensitivity/abstract_object_statistics.h @@ -1,3 +1,11 @@ +/*******************************************************************\ + +Module: Variable Sensitivity Domain + +Author: Hannes Steffenhagen + +\*******************************************************************/ + #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_STATISTICS_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_STATISTICS_H diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index f2dde76cb99..a73e535c3dd 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -24,12 +24,12 @@ class array_abstract_objectt : public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - virtual abstract_object_pointert read( + abstract_object_pointert read( const abstract_environmentt &env, const exprt &specifier, const namespacet &ns) const override; - virtual abstract_object_pointert write( + abstract_object_pointert write( abstract_environmentt &environment, const namespacet &ns, const std::stack stack, diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index d9f5f46deec..f10b5fb135d 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -48,7 +48,7 @@ abstract_object_pointert constant_abstract_valuet::expression_transform( // try finding the rounding mode. If it's not constant, try // seeing if we can get the same result with all rounding modes auto rounding_mode_symbol = - symbol_exprt("__CPROVER_rounding_mode", signedbv_typet(32)); + symbol_exprt(CPROVER_PREFIX "rounding_mode", signedbv_typet(32)); auto rounding_mode_value = environment.eval(rounding_mode_symbol, ns); auto rounding_mode_constant = rounding_mode_value->to_constant(); if(rounding_mode_constant.is_nil()) @@ -103,7 +103,7 @@ constant_abstract_valuet::try_transform_expr_with_all_rounding_modes( const namespacet &ns) const { const symbol_exprt rounding_mode_symbol = - symbol_exprt("__CPROVER_rounding_mode", signedbv_typet(32)); + symbol_exprt(CPROVER_PREFIX "rounding_mode", signedbv_typet(32)); // NOLINTNEXTLINE (whitespace/braces) auto rounding_modes = std::array{ // NOLINTNEXTLINE (whitespace/braces) diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 83f5fd5e768..9c54aab50a7 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -31,15 +31,15 @@ class constant_abstract_valuet : public abstract_valuet { } - virtual abstract_object_pointert expression_transform( + abstract_object_pointert expression_transform( const exprt &expr, const std::vector &operands, const abstract_environmentt &environment, const namespacet &ns) const override; - virtual exprt to_constant() const override; + exprt to_constant() const override; - virtual void output( + void output( std::ostream &out, const class ai_baset &ai, const class namespacet &ns) const override; @@ -64,8 +64,7 @@ class constant_abstract_valuet : public abstract_valuet protected: CLONE - virtual abstract_object_pointert - merge(abstract_object_pointert other) const override; + abstract_object_pointert merge(abstract_object_pointert other) const override; abstract_object_pointert try_transform_expr_with_all_rounding_modes( const exprt &expr, diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 22b3952a090..b9543022d6c 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -183,7 +183,7 @@ abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( mutable_clone()); bool modified = - abstract_objectt::merge_shared_maps( + abstract_objectt::merge_shared_maps( map, other->map, result->map); if(!modified) diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index 16883a79d0c..287e6e524d2 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -37,7 +37,7 @@ class constant_array_abstract_objectt : public array_abstract_objectt void output(std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; - virtual abstract_object_pointert + abstract_object_pointert visit_sub_elements(const abstract_object_visitort &visitor) const override; void get_statistics( @@ -49,12 +49,12 @@ class constant_array_abstract_objectt : public array_abstract_objectt protected: CLONE - virtual abstract_object_pointert read_index( + abstract_object_pointert read_index( const abstract_environmentt &env, const index_exprt &index, const namespacet &ns) const override; - virtual sharing_ptrt write_index( + sharing_ptrt write_index( abstract_environmentt &environment, const namespacet &ns, const std::stack stack, @@ -62,11 +62,10 @@ class constant_array_abstract_objectt : public array_abstract_objectt const abstract_object_pointert value, bool merging_write) const override; - virtual abstract_object_pointert - merge(abstract_object_pointert other) const override; + abstract_object_pointert merge(abstract_object_pointert other) const override; - virtual bool verify() const override; - virtual void make_top_internal() override; + bool verify() const override; + void make_top_internal() override; virtual bool eval_index( const index_exprt &index, @@ -78,7 +77,7 @@ class constant_array_abstract_objectt : public array_abstract_objectt // 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 - struct mp_integer_hash + struct mp_integer_hasht { size_t operator()(const mp_integer &i) const { @@ -90,7 +89,7 @@ class constant_array_abstract_objectt : public array_abstract_objectt mp_integer, abstract_object_pointert, false, - mp_integer_hash> + mp_integer_hasht> shared_array_mapt; shared_array_mapt map; diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 782d18e39f0..dc677e99f3f 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -54,8 +54,7 @@ class constant_pointer_abstract_objectt : public pointer_abstract_objectt const namespacet &ns) const override; protected: - virtual abstract_object_pointert - merge(abstract_object_pointert op1) const override; + abstract_object_pointert merge(abstract_object_pointert op1) const override; CLONE diff --git a/src/analyses/variable-sensitivity/context_abstract_object.h b/src/analyses/variable-sensitivity/context_abstract_object.h index 2fbe2e83339..453b1b756c2 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.h +++ b/src/analyses/variable-sensitivity/context_abstract_object.h @@ -59,17 +59,17 @@ class context_abstract_objectt : public abstract_objectt return child_abstract_object->type(); } - virtual bool is_top() const override + bool is_top() const override { return child_abstract_object->is_top(); } - virtual bool is_bottom() const override + bool is_bottom() const override { return child_abstract_object->is_bottom(); } - virtual exprt to_constant() const override + exprt to_constant() const override { return child_abstract_object->to_constant(); } @@ -80,10 +80,8 @@ class context_abstract_objectt : public abstract_objectt const abstract_environmentt &environment, const namespacet &ns) const override; - virtual void output( - std::ostream &out, - const class ai_baset &ai, - const namespacet &ns) const override; + void output(std::ostream &out, const class ai_baset &ai, const namespacet &ns) + const override; abstract_object_pointert unwrap_context() const override; @@ -105,15 +103,15 @@ class context_abstract_objectt : public abstract_objectt // These are internal hooks that allow sub-classes to perform additional // actions when an abstract_object is set/unset to TOP - virtual void make_top_internal() override; - virtual void clear_top_internal() override; + void make_top_internal() override; + void clear_top_internal() override; - virtual abstract_object_pointert read( + abstract_object_pointert read( const abstract_environmentt &env, const exprt &specifier, const namespacet &ns) const override; - virtual abstract_object_pointert write( + abstract_object_pointert write( abstract_environmentt &environment, const namespacet &ns, const std::stack stack, @@ -121,8 +119,7 @@ class context_abstract_objectt : public abstract_objectt const abstract_object_pointert value, bool merging_write) const override; - virtual bool - has_been_modified(const abstract_object_pointert before) const override; + bool has_been_modified(const abstract_object_pointert before) const override; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONTEXT_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/data_dependency_context.h b/src/analyses/variable-sensitivity/data_dependency_context.h index c9532d8330a..26c824ac49d 100644 --- a/src/analyses/variable-sensitivity/data_dependency_context.h +++ b/src/analyses/variable-sensitivity/data_dependency_context.h @@ -47,7 +47,7 @@ class data_dependency_contextt : public write_location_contextt { } - virtual abstract_object_pointert write( + abstract_object_pointert write( abstract_environmentt &environment, const namespacet &ns, const std::stack stack, @@ -55,7 +55,7 @@ class data_dependency_contextt : public write_location_contextt const abstract_object_pointert value, bool merging_write) const override; - virtual abstract_object_pointert update_location_context( + abstract_object_pointert update_location_context( const abstract_objectt::locationst &locations, const bool update_sub_elements) const override; @@ -64,18 +64,15 @@ class data_dependency_contextt : public write_location_contextt std::set get_data_dependencies() const; std::set get_data_dominators() const; - virtual void output( - std::ostream &out, - const class ai_baset &ai, - const namespacet &ns) const override; + void output(std::ostream &out, const class ai_baset &ai, const namespacet &ns) + const override; protected: CLONE - virtual abstract_object_pointert - merge(abstract_object_pointert other) const override; + abstract_object_pointert merge(abstract_object_pointert other) const override; - virtual abstract_object_pointert abstract_object_merge_internal( + abstract_object_pointert abstract_object_merge_internal( const abstract_object_pointert other) const override; private: diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 49b16aaffd2..0ea117565f7 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -145,8 +145,7 @@ abstract_object_pointert full_struct_abstract_objectt::read_component( const namespacet &ns) const { #ifdef DEBUG - std::cout << "Reading component " << member_expr.get_component_name() - << std::endl; + std::cout << "Reading component " << member_expr.get_component_name() << '\n'; #endif if(is_top()) @@ -203,8 +202,7 @@ full_struct_abstract_objectt::write_component( bool merging_write) const { #ifdef DEBUG - std::cout << "Writing component " << member_expr.get_component_name() - << std::endl; + std::cout << "Writing component " << member_expr.get_component_name() << '\n'; #endif if(is_bottom()) diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index d55858e9e85..bb3ab68bdc5 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -35,12 +35,12 @@ class full_struct_abstract_objectt : public struct_abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - virtual void output( + void output( std::ostream &out, const class ai_baset &ai, const class namespacet &ns) const override; - virtual abstract_object_pointert + abstract_object_pointert visit_sub_elements(const abstract_object_visitort &visitor) const override; void get_statistics( @@ -62,12 +62,12 @@ class full_struct_abstract_objectt : public struct_abstract_objectt CLONE // struct interface - virtual abstract_object_pointert read_component( + abstract_object_pointert read_component( const abstract_environmentt &environment, const member_exprt &member_expr, const namespacet &ns) const override; - virtual sharing_ptrt write_component( + sharing_ptrt write_component( abstract_environmentt &environment, const namespacet &ns, const std::stack &stack, @@ -75,11 +75,10 @@ class full_struct_abstract_objectt : public struct_abstract_objectt const abstract_object_pointert value, bool merging_write) const override; - virtual bool verify() const override; + bool verify() const override; // Set the state of this to the merge result of op1 and op2 and // return if the result is different from op1 - virtual abstract_object_pointert - merge(abstract_object_pointert other) const override; + abstract_object_pointert merge(abstract_object_pointert other) const override; }; #endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_FULL_STRUCT_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h index d26fa49dcef..ae99ad34e77 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.h +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -37,7 +37,7 @@ class interval_abstract_valuet : public abstract_valuet ~interval_abstract_valuet() override = default; - virtual exprt to_constant() const override; + exprt to_constant() const override; // Interface for transforms abstract_object_pointert expression_transform( @@ -46,7 +46,7 @@ class interval_abstract_valuet : public abstract_valuet const abstract_environmentt &environment, const namespacet &ns) const override; - virtual void output( + void output( std::ostream &out, const class ai_baset &ai, const class namespacet &ns) const override; @@ -61,8 +61,7 @@ class interval_abstract_valuet : public abstract_valuet protected: CLONE - virtual abstract_object_pointert - merge(abstract_object_pointert other) const override; + abstract_object_pointert merge(abstract_object_pointert other) const override; abstract_object_pointert meet(const abstract_object_pointert &other) const override; diff --git a/src/analyses/variable-sensitivity/interval_array_abstract_object.h b/src/analyses/variable-sensitivity/interval_array_abstract_object.h index b57d478046c..f3f7a1b216d 100644 --- a/src/analyses/variable-sensitivity/interval_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/interval_array_abstract_object.h @@ -6,8 +6,8 @@ Author: Diffblue Ltd. \*******************************************************************/ -#ifndef PROJECT_INTERVAL_ARRAY_ABSTRACT_OBJECTT_H -#define PROJECT_INTERVAL_ARRAY_ABSTRACT_OBJECTT_H +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_INTERVAL_ARRAY_ABSTRACT_OBJECT_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_INTERVAL_ARRAY_ABSTRACT_OBJECT_H #include "constant_array_abstract_object.h" @@ -52,4 +52,4 @@ class interval_array_abstract_objectt : public constant_array_abstract_objectt const namespacet &ns) const override; }; -#endif //PROJECT_INTERVAL_ARRAY_ABSTRACT_OBJECTT_H +#endif // CPROVER_ANALYSES_VARIABLE_SENSITIVITY_INTERVAL_ARRAY_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index 6e908901e06..82829b427d7 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -26,12 +26,12 @@ class pointer_abstract_objectt : public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - virtual abstract_object_pointert read( + abstract_object_pointert read( const abstract_environmentt &env, const exprt &specifier, const namespacet &ns) const override; - virtual abstract_object_pointert write( + abstract_object_pointert write( abstract_environmentt &environment, const namespacet &ns, const std::stack stack, diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index 06155524221..5d2f02ffe93 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -25,12 +25,12 @@ class struct_abstract_objectt : public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - virtual abstract_object_pointert read( + abstract_object_pointert read( const abstract_environmentt &env, const exprt &specifier, const namespacet &ns) const override; - virtual abstract_object_pointert write( + abstract_object_pointert write( abstract_environmentt &environment, const namespacet &ns, const std::stack stack, diff --git a/src/analyses/variable-sensitivity/union_abstract_object.h b/src/analyses/variable-sensitivity/union_abstract_object.h index 9ec22d28aab..5bcb503446b 100644 --- a/src/analyses/variable-sensitivity/union_abstract_object.h +++ b/src/analyses/variable-sensitivity/union_abstract_object.h @@ -25,12 +25,12 @@ class union_abstract_objectt : public abstract_objectt const abstract_environmentt &environment, const namespacet &ns); - virtual abstract_object_pointert read( + abstract_object_pointert read( const abstract_environmentt &env, const exprt &specifier, const namespacet &ns) const override; - virtual abstract_object_pointert write( + abstract_object_pointert write( abstract_environmentt &environment, const namespacet &ns, const std::stack stack, diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index fb5a2f89642..24e8e5b3e63 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -76,7 +76,8 @@ void variable_sensitivity_dependence_domaint::transform( variable_sensitivity_dependence_grapht *dep_graph = dynamic_cast(&ai); - assert(dep_graph != nullptr); + DATA_INVARIANT( + dep_graph != nullptr, "Domains should all be of the same type"); // propagate control dependencies across function calls if(from->is_function_call()) @@ -93,7 +94,7 @@ void variable_sensitivity_dependence_domaint::transform( variable_sensitivity_dependence_domaint *s = dynamic_cast( &(dep_graph->get_state(next))); - assert(s != nullptr); + DATA_INVARIANT(s != nullptr, "Domains should all be of the same type"); if(s->has_values.is_false()) { @@ -334,9 +335,12 @@ bool variable_sensitivity_dependence_domaint::merge_control_dependencies( } else { - assert(it != control_deps.end()); - assert(!(it->first < c_dep.first)); - assert(!(c_dep.first < it->first)); + INVARIANT( + it != control_deps.end(), "Property of branch needed for safety"); + INVARIANT( + !(it->first < c_dep.first), "Property of loop needed for safety"); + INVARIANT( + !(c_dep.first < it->first), "Property of loop needed for safety"); tvt &branch1 = it->second; const tvt &branch2 = c_dep.second; @@ -641,9 +645,9 @@ void variable_sensitivity_dependence_grapht::add_dep( goto_programt::const_targett to) { const node_indext n_from = (*this)[from].get_node_id(); - assert(n_from < size()); + DATA_INVARIANT(n_from < size(), "Node ids must be within the graph"); const node_indext n_to = (*this)[to].get_node_id(); - assert(n_to < size()); + DATA_INVARIANT(n_to < size(), "Node ids must be within the graph"); // add_edge is redundant as the subsequent operations also insert // entries into the edge maps (implicitly) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h index 574d8b20316..fb94c0852b1 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -82,7 +82,7 @@ class variable_sensitivity_dependence_domaint ai_baset &ai, const namespacet &ns) override; - virtual void make_bottom() override + void make_bottom() override { variable_sensitivity_domaint::make_bottom(); has_values = tvt(false); @@ -94,7 +94,7 @@ class variable_sensitivity_dependence_domaint control_dep_call_candidates.clear(); } - virtual void make_top() override + void make_top() override { variable_sensitivity_domaint::make_top(); has_values = tvt(true); @@ -106,7 +106,7 @@ class variable_sensitivity_dependence_domaint control_dep_call_candidates.clear(); } - virtual void make_entry() override + void make_entry() override { make_top(); } @@ -121,12 +121,12 @@ class variable_sensitivity_dependence_domaint return variable_sensitivity_domaint::is_top() && has_values.is_true(); } - virtual bool merge( + bool merge( const variable_sensitivity_domaint &b, locationt from, locationt to) override; - virtual void merge_three_way_function_return( + void merge_three_way_function_return( const ai_domain_baset &function_call, const ai_domain_baset &function_start, const ai_domain_baset &function_end, @@ -143,7 +143,9 @@ class variable_sensitivity_dependence_domaint node_indext get_node_id() const { - assert(node_id != std::numeric_limits::max()); + DATA_INVARIANT( + node_id != std::numeric_limits::max(), + "Check for the old uninitialised value"); return node_id; } diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 95ddcb460b1..e4a5f806ddf 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -44,8 +44,7 @@ void variable_sensitivity_domaint::transform( { #ifdef DEBUG std::cout << "Transform from/to:\n"; - std::cout << from->location_number << " --> " << to->location_number - << std::endl; + std::cout << from->location_number << " --> " << to->location_number << '\n'; #endif const goto_programt::instructiont &instruction = *from; @@ -278,7 +277,7 @@ bool variable_sensitivity_domaint::merge( { #ifdef DEBUG std::cout << "Merging from/to:\n " << from->location_number << " --> " - << to->location_number << std::endl; + << to->location_number << '\n'; #endif // Use the abstract_environment merge diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 48efd22a344..70593c0e4ea 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -72,7 +72,7 @@ into calls to eval, assume, assign and merge. class variable_sensitivity_domaint : public ai_domain_baset { public: - virtual void transform( + void transform( const irep_idt &function_from, locationt from, const irep_idt &function_to, @@ -81,18 +81,16 @@ class variable_sensitivity_domaint : public ai_domain_baset const namespacet &ns) override; // no states - virtual void make_bottom() override; + void make_bottom() override; // all states - virtual void make_top() override; + void make_top() override; // a reasonable entry-point state - virtual void make_entry() override; + void make_entry() override; - virtual void output( - std::ostream &out, - const ai_baset &ai, - const namespacet &ns) const override; + void output(std::ostream &out, const ai_baset &ai, const namespacet &ns) + const override; void output(std::ostream &out) const; diff --git a/src/analyses/variable-sensitivity/write_location_context.h b/src/analyses/variable-sensitivity/write_location_context.h index d29c1a5fd6b..229ef7fe383 100644 --- a/src/analyses/variable-sensitivity/write_location_context.h +++ b/src/analyses/variable-sensitivity/write_location_context.h @@ -65,10 +65,9 @@ class write_location_contextt : public context_abstract_objectt // Standard abstract_objectt interface - virtual bool - has_been_modified(const abstract_object_pointert before) const override; + bool has_been_modified(const abstract_object_pointert before) const override; - virtual abstract_object_pointert update_location_context( + abstract_object_pointert update_location_context( const abstract_objectt::locationst &locations, const bool update_sub_elements) const override; @@ -94,21 +93,18 @@ class write_location_contextt : public context_abstract_objectt locationst get_location_union(const locationst &locations) const; - virtual void output( - std::ostream &out, - const class ai_baset &ai, - const namespacet &ns) const override; + void output(std::ostream &out, const class ai_baset &ai, const namespacet &ns) + const override; protected: CLONE - virtual abstract_object_pointert - merge(abstract_object_pointert other) const override; + abstract_object_pointert merge(abstract_object_pointert other) const override; - virtual abstract_object_pointert abstract_object_merge_internal( + abstract_object_pointert abstract_object_merge_internal( const abstract_object_pointert other) const override; - virtual abstract_object_pointert write( + abstract_object_pointert write( abstract_environmentt &environment, const namespacet &ns, const std::stack stack, diff --git a/src/analyses/variable-sensitivity/write_stack_entry.h b/src/analyses/variable-sensitivity/write_stack_entry.h index b4d8643bff5..5d58548aaa4 100644 --- a/src/analyses/variable-sensitivity/write_stack_entry.h +++ b/src/analyses/variable-sensitivity/write_stack_entry.h @@ -35,8 +35,8 @@ class simple_entryt : public write_stack_entryt { public: explicit simple_entryt(exprt expr); - virtual exprt get_access_expr() const override; - virtual void adjust_access_type(exprt &expr) const override; + exprt get_access_expr() const override; + void adjust_access_type(exprt &expr) const override; private: exprt simple_entry; @@ -46,9 +46,9 @@ class offset_entryt : public write_stack_entryt { public: explicit offset_entryt(abstract_object_pointert offset_value); - virtual exprt get_access_expr() const override; - virtual void adjust_access_type(exprt &expr) const override; - virtual bool try_squash_in( + exprt get_access_expr() const override; + void adjust_access_type(exprt &expr) const override; + bool try_squash_in( std::shared_ptr new_entry, const abstract_environmentt &enviroment, const namespacet &ns) override; diff --git a/src/util/std_expr.h b/src/util/std_expr.h index 03e6671631f..d0d0c7b28cb 100644 --- a/src/util/std_expr.h +++ b/src/util/std_expr.h @@ -114,9 +114,11 @@ class symbol_exprt : public nullary_exprt } }; +// NOLINTNEXTLINE(readability/namespace) namespace std { template <> +// NOLINTNEXTLINE(readability/identifiers) struct hash<::symbol_exprt> { size_t operator()(const ::symbol_exprt &sym) diff --git a/unit/analyses/variable-sensitivity/abstract_object/module_dependencies.txt b/unit/analyses/variable-sensitivity/abstract_object/module_dependencies.txt new file mode 100644 index 00000000000..ac96be3c1ef --- /dev/null +++ b/unit/analyses/variable-sensitivity/abstract_object/module_dependencies.txt @@ -0,0 +1,3 @@ +analyses +testing-utils +util diff --git a/unit/analyses/variable-sensitivity/constant_abstract_value/module_dependencies.txt b/unit/analyses/variable-sensitivity/constant_abstract_value/module_dependencies.txt new file mode 100644 index 00000000000..ac96be3c1ef --- /dev/null +++ b/unit/analyses/variable-sensitivity/constant_abstract_value/module_dependencies.txt @@ -0,0 +1,3 @@ +analyses +testing-utils +util diff --git a/unit/analyses/variable-sensitivity/constant_array_abstract_object/module_dependencies.txt b/unit/analyses/variable-sensitivity/constant_array_abstract_object/module_dependencies.txt new file mode 100644 index 00000000000..ac96be3c1ef --- /dev/null +++ b/unit/analyses/variable-sensitivity/constant_array_abstract_object/module_dependencies.txt @@ -0,0 +1,3 @@ +analyses +testing-utils +util diff --git a/unit/analyses/variable-sensitivity/full_struct_abstract_object/module_dependencies.txt b/unit/analyses/variable-sensitivity/full_struct_abstract_object/module_dependencies.txt new file mode 100644 index 00000000000..ac96be3c1ef --- /dev/null +++ b/unit/analyses/variable-sensitivity/full_struct_abstract_object/module_dependencies.txt @@ -0,0 +1,3 @@ +analyses +testing-utils +util diff --git a/unit/analyses/variable-sensitivity/interval_abstract_value/module_dependencies.txt b/unit/analyses/variable-sensitivity/interval_abstract_value/module_dependencies.txt new file mode 100644 index 00000000000..f4c536408fa --- /dev/null +++ b/unit/analyses/variable-sensitivity/interval_abstract_value/module_dependencies.txt @@ -0,0 +1,3 @@ +analyses +testing-utils + diff --git a/unit/analyses/variable-sensitivity/last_written_location.cpp b/unit/analyses/variable-sensitivity/last_written_location.cpp index 569d3278c4b..7769f2d631c 100644 --- a/unit/analyses/variable-sensitivity/last_written_location.cpp +++ b/unit/analyses/variable-sensitivity/last_written_location.cpp @@ -27,7 +27,7 @@ #include #include -//#include +// #include SCENARIO( "Constructing two environments to make sure we correctly identify modified " @@ -104,8 +104,8 @@ SCENARIO( namespacet ns(symbol_table); WHEN( - "The identifiers get inserted into two environments, but one of \ - them has a different value in one of the environments") + "The identifiers get inserted into two environments, but one of " + "them has a different value in one of the environments") { abstract_environmentt env; diff --git a/unit/analyses/variable-sensitivity/module_dependencies.txt b/unit/analyses/variable-sensitivity/module_dependencies.txt new file mode 100644 index 00000000000..ac96be3c1ef --- /dev/null +++ b/unit/analyses/variable-sensitivity/module_dependencies.txt @@ -0,0 +1,3 @@ +analyses +testing-utils +util From d9cc8ac3b4a9a54fa643e5cd7724dd5cc1846d13 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 10 Aug 2020 15:15:48 +0100 Subject: [PATCH 319/342] Fix a very subtle bug in the initialisation of VSD domain objects The default state of a domain on construction should be bottom. This is documented in the ai_domaint interface. As the variable_sensitivity_domaint delegates the handling of bottom to the abstract_environment, it must be initialised to bottom in the default case. --- 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 6ad9413ffbd..f8239c56b32 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -803,6 +803,6 @@ abstract_environmentt::gather_statistics(const namespacet &ns) const return statistics; } -abstract_environmentt::abstract_environmentt() : bottom(false) +abstract_environmentt::abstract_environmentt() : bottom(true) { } From 2ef5c1d6c99253459cd5ab51eb7286c73c26be6b Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 10 Aug 2020 17:46:13 +0100 Subject: [PATCH 320/342] Integrate VSD so that it can be called from goto-analyzer The command-line flags are backwards compatable with older versions of this code where possible. --- .../goto_analyzer_parse_options.cpp | 65 +++++++++++++++++++ .../goto_analyzer_parse_options.h | 15 ++++- src/goto-analyzer/static_show_domain.cpp | 39 ++++++++--- 3 files changed, 109 insertions(+), 10 deletions(-) diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index 57236b4a6dd..0573e86cd83 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -51,6 +51,9 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include +#include +#include #include #include @@ -356,6 +359,31 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) options.set_option("non-null", true); options.set_option("domain set", true); } + else if(cmdline.isset("vsd") || cmdline.isset("variable-sensitivity")) + { + options.set_option("vsd", true); + options.set_option("domain set", true); + + // Configuration of VSD + options.set_option("pointers", cmdline.isset("vsd-pointers")); + options.set_option("arrays", cmdline.isset("vsd-arrays")); + options.set_option("structs", cmdline.isset("vsd-structs")); + options.set_option( + "data-dependencies", cmdline.isset("vsd-data-dependencies")); + options.set_option("interval", cmdline.isset("vsd-intervals")); + options.set_option("value-set", cmdline.isset("vsd-value-sets")); + } + else if(cmdline.isset("dependence-graph-vs")) + { + options.set_option("dependence-graph-vs", true); + options.set_option("domain set", true); + + // Configuration of variable sensitivity domain + options.set_option("pointers", cmdline.isset("vsd-pointers")); + options.set_option("arrays", cmdline.isset("vsd-arrays")); + options.set_option("structs", cmdline.isset("vsd-structs")); + options.set_option("data-dependencies", true); + } // Reachability questions, when given with a domain swap from specific // to general tasks so that they can use the domain & parameterisations. @@ -450,8 +478,14 @@ ai_baset *goto_analyzer_parse_optionst::build_analyzer( df = util_make_unique< ai_domain_factory_default_constructort>(); } + else if(options.get_bool_option("vsd")) + { + df = util_make_unique< + ai_domain_factory_default_constructort>(); + } // non-null is not fully supported, despite the historical options // dependency-graph is quite heavily tied to the legacy-ait infrastructure + // dependency-graph-vs is very similar to dependency-graph // Build the storage object std::unique_ptr st = nullptr; @@ -487,6 +521,15 @@ ai_baset *goto_analyzer_parse_optionst::build_analyzer( { return new dependence_grapht(ns); } + else if(options.get_bool_option("dependence-graph-vs")) + { + return new variable_sensitivity_dependence_grapht( + goto_model.goto_functions, ns); + } + else if(options.get_bool_option("vsd")) + { + return new ait(); + } else if(options.get_bool_option("intervals")) { return new ait(); @@ -702,6 +745,18 @@ int goto_analyzer_parse_optionst::perform_analysis(const optionst &options) if(options.get_bool_option("general-analysis")) { + // TODO : replace with the domain factory infrastructure + try + { + variable_sensitivity_object_factoryt::instance().set_options( + vsd_configt::from_options(options)); + } + catch(const invalid_command_line_argument_exceptiont &e) + { + log.error() << e.what() << messaget::eom; + return CPROVER_EXIT_USAGE_ERROR; + } + // Output file factory const std::string outfile=options.get_option("outfile"); @@ -915,6 +970,16 @@ void goto_analyzer_parse_optionst::help() " --intervals an interval for each variable\n" " --non-null tracks which pointers are non-null\n" " --dependence-graph data and control dependencies between instructions\n" // NOLINT(*) + " --vsd a configurable non-relational domain\n" // NOLINT(*) + " --dependence-graph-vs dependencies between instructions using VSD\n" // NOLINT(*) + "\n" + "Variable sensitivity domain (VSD) options:\n" + " --vsd-structs struct field sensitive analysis\n" + " --vsd-arrays array entry sensitive analysis\n" + " --vsd-pointers pointer sensitive analysis\n" + " --vsd-value-sets use value sets\n" + " --vsd-data-dependencies track data dependencies\n" + " --vsd-intervals use intervals\n" "\n" "Storage options:\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 4e745c28aee..409fbf341a9 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.h +++ b/src/goto-analyzer/goto_analyzer_parse_options.h @@ -129,7 +129,17 @@ class optionst; "(intervals)" \ "(non-null)" \ "(constants)" \ - "(dependence-graph)" + "(dependence-graph)" \ + "(vsd)(variable-sensitivity)" \ + "(dependence-graph-vs)" \ + +#define GOTO_ANALYSER_OPTIONS_VSD \ + "(vsd-structs)" \ + "(vsd-arrays)" \ + "(vsd-pointers)" \ + "(vsd-value-sets)" \ + "(vsd-data-dependencies)" \ + "(vsd-intervals)" \ #define GOTO_ANALYSER_OPTIONS_STORAGE \ "(one-domain-per-history)" \ @@ -167,7 +177,8 @@ class optionst; "(location-sensitive)(concurrent)" \ GOTO_ANALYSER_OPTIONS_HISTORY \ GOTO_ANALYSER_OPTIONS_DOMAIN \ - GOTO_ANALYSER_OPTIONS_STORAGE \ + GOTO_ANALYSER_OPTIONS_VSD \ + GOTO_ANALYSER_OPTIONS_STORAGE \ GOTO_ANALYSER_OPTIONS_OUTPUT \ GOTO_ANALYSER_OPTIONS_SPECIFIC_ANALYSES \ // clang-format on diff --git a/src/goto-analyzer/static_show_domain.cpp b/src/goto-analyzer/static_show_domain.cpp index 3fe68b43495..3d0b132268c 100644 --- a/src/goto-analyzer/static_show_domain.cpp +++ b/src/goto-analyzer/static_show_domain.cpp @@ -11,6 +11,7 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk #include #include +#include /// Runs the analyzer and then prints out the domain /// \param goto_model: the program analyzed @@ -31,16 +32,38 @@ void static_show_domain( { out << ai.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") || + options.get_bool_option("dependence-graph-vs"))) { - const dependence_grapht *d=dynamic_cast(&ai); - INVARIANT(d!=nullptr, - "--dependence-graph sets ai to be a dependence_graph"); + // It would be nice to cast this to a grapht but C++ templates and + // inheritance need some care to work together. + if(options.get_bool_option("dependence-graph")) + { + auto d = dynamic_cast(&ai); + INVARIANT( + d != nullptr, + "--dependence-graph should set ai to be a dependence_grapht"); - out << "digraph g {\n"; - d->output_dot(out); - out << "}\n"; + out << "digraph g {\n"; + d->output_dot(out); + out << "}\n"; + } + else if(options.get_bool_option("dependence-graph-vs")) + { + auto d = + dynamic_cast(&ai); + INVARIANT( + d != nullptr, + "--dependence-graph-vsd should set ai to be a " + "variable_sensitivity_dependence_grapht"); + + out << "digraph g {\n"; + d->output_dot(out); + out << "}\n"; + } + UNREACHABLE; } else { From 7c5c64a5289e75b4637ad7453dbb295b3ec5c99e Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 10 Aug 2020 17:48:28 +0100 Subject: [PATCH 321/342] Update the regression tests for the new arguments --- .../goto-analyzer-simplify/partial-simplify-array/test.desc | 2 +- .../simplify-complex-expression/test.desc | 4 ++-- .../goto-analyzer-simplify/simplify-lhs-array-index/test.desc | 2 +- .../simplify-lhs-array-pointers-index/test.desc | 2 +- .../goto-analyzer-simplify/simplify-lhs-dereference/test.desc | 2 +- .../goto-analyzer-simplify/simplify-lhs-member/test.desc | 2 +- .../simplify-lhs-pointer-array-dereference/test.desc | 2 +- .../simplify-multiply-by-zero/test.desc | 2 +- regression/goto-analyzer/constant_assertions_01/test.desc | 2 +- regression/goto-analyzer/constant_assertions_02/test.desc | 2 +- .../goto-analyzer/constant_propagation_01/test-vsd.desc | 2 +- .../goto-analyzer/constant_propagation_02/test-vsd.desc | 2 +- .../goto-analyzer/constant_propagation_03/test-vsd.desc | 2 +- .../goto-analyzer/constant_propagation_04/test-vsd.desc | 2 +- .../goto-analyzer/constant_propagation_05/test-vsd.desc | 2 +- .../goto-analyzer/constant_propagation_06/test-vsd.desc | 2 +- .../goto-analyzer/constant_propagation_07/test-vsd.desc | 2 +- .../goto-analyzer/constant_propagation_08/test-vsd.desc | 2 +- regression/goto-analyzer/constant_propagation_08/test.desc | 2 +- .../goto-analyzer/constant_propagation_09/test-vsd.desc | 2 +- regression/goto-analyzer/constant_propagation_09/test.desc | 2 +- .../goto-analyzer/constant_propagation_10/test-vsd.desc | 2 +- regression/goto-analyzer/constant_propagation_10/test.desc | 2 +- .../goto-analyzer/constant_propagation_11/test-vsd.desc | 2 +- regression/goto-analyzer/constant_propagation_11/test.desc | 2 +- .../goto-analyzer/constant_propagation_12/test-vsd.desc | 2 +- .../goto-analyzer/constant_propagation_13/test-vsd.desc | 2 +- .../goto-analyzer/constant_propagation_14/test-vsd.desc | 2 +- regression/goto-analyzer/constant_propagation_14/test.desc | 2 +- .../goto-analyzer/constant_propagation_15/test-vsd.desc | 2 +- regression/goto-analyzer/constant_propagation_15/test.desc | 2 +- .../goto-analyzer/constant_propagation_16/test-vsd.desc | 2 +- .../goto-analyzer/constant_propagation_17/test-vsd.desc | 2 +- .../goto-analyzer/constant_propagation_18/test-vsd.desc | 2 +- .../goto-analyzer/constant_propagation_19/test-vsd.desc | 2 +- .../minimal-reproducer-for-struct-problem/test.desc | 2 +- .../goto-analyzer/sensitivity-function-call-array/test.desc | 2 +- .../goto-analyzer/sensitivity-function-call-opaque/test.desc | 2 +- .../goto-analyzer/sensitivity-function-call-pointer/test.desc | 2 +- .../sensitivity-function-call-primitive/test.desc | 2 +- .../sensitivity-function-call-recursive/test.desc | 2 +- .../goto-analyzer/sensitivity-function-call-varargs/test.desc | 2 +- .../sensitivity-last-written-locations-arrays/test.desc | 2 +- .../sensitivity-last-written-locations-pointers/test.desc | 2 +- .../sensitivity-last-written-locations-structs/test.desc | 2 +- .../sensitivity-last-written-locations-variables/test.desc | 2 +- .../sensitivity-test-constants-array-loop/test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../goto-analyzer/sensitivity-test-constants-array/test.desc | 2 +- .../goto-analyzer/sensitivity-test-constants-char/test.desc | 2 +- .../goto-analyzer/sensitivity-test-constants-float/test.desc | 2 +- .../goto-analyzer/sensitivity-test-constants-int/test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../sensitivity-test-constants-pointer/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 +- .../sensitivity-test-data-dependency-context/test.desc | 2 +- .../sensitivity-test-struct-initialization/test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../goto-analyzer/sensitivity-test-two-value-array/test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../sensitivity-test-two-value-pointer/test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../goto-analyzer/sensitivity-test-two-value-struct/test.desc | 2 +- regression/goto-analyzer/unreachable_assertions_01/test.desc | 2 +- .../value-set-function-pointers-arrays/test.desc | 2 +- .../value-set-function-pointers-incremented/test.desc | 2 +- .../value-set-function-pointers-simple/test.desc | 2 +- .../value-set-function-pointers-structs/test.desc | 2 +- regression/goto-analyzer/value-set-simple/test_show.desc | 2 +- regression/goto-analyzer/value-set-simple/test_verify.desc | 2 +- regression/goto-analyzer/value-set-structs/test_show.desc | 2 +- regression/goto-analyzer/value-set-structs/test_verify.desc | 2 +- .../variable-sensitivity-annihiliator-test/test.desc | 2 +- .../variable-sensitivity-assign-aware-merge-array/test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../variable-sensitivity-assign-aware-merge-simple/test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../variable-sensitivity-assign-aware-merge-struct/test.desc | 2 +- .../variable-sensitivity-bit-field-constants/test.desc | 2 +- .../variable-sensitivity-bit-field-intervals/test.desc | 2 +- .../goto-analyzer/variable-sensitivity-bug-01/test.desc | 2 +- .../goto-analyzer/variable-sensitivity-bug-02/test.desc | 2 +- .../goto-analyzer/variable-sensitivity-bug-03/test.desc | 2 +- .../variable-sensitivity-dependence-graph-merge/test.desc | 2 +- .../variable-sensitivity-dependence-graph-toyota/test.desc | 2 +- .../variable-sensitivity-dependence-graph/test.desc | 2 +- .../variable-sensitivity-dependence-graph17/test.desc | 2 +- .../test.desc | 2 +- .../variable-sensitivity-interval-values-arith-01/test.desc | 2 +- .../variable-sensitivity-interval-values-arith-02/test.desc | 2 +- .../variable-sensitivity-interval-values-arith-03/test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../variable-sensitivity-interval-values-float/test.desc | 2 +- .../variable-sensitivity-interval-values-logical-01/test.desc | 2 +- .../test.desc | 2 +- .../test.desc | 2 +- .../variable-sensitivity-interval-values/test.desc | 2 +- regression/goto-analyzer/write-stack-types/test.desc | 2 +- 118 files changed, 119 insertions(+), 119 deletions(-) diff --git a/regression/goto-analyzer-simplify/partial-simplify-array/test.desc b/regression/goto-analyzer-simplify/partial-simplify-array/test.desc index e5a2885215a..7c0b5afe8c1 100644 --- a/regression/goto-analyzer-simplify/partial-simplify-array/test.desc +++ b/regression/goto-analyzer-simplify/partial-simplify-array/test.desc @@ -1,5 +1,5 @@ CORE main.c -"--variable --arrays" +"--variable-sensitivity --vsd-arrays" arr\[0l\] diff --git a/regression/goto-analyzer-simplify/simplify-complex-expression/test.desc b/regression/goto-analyzer-simplify/simplify-complex-expression/test.desc index 289cd7d363b..2e489c2332f 100644 --- a/regression/goto-analyzer-simplify/simplify-complex-expression/test.desc +++ b/regression/goto-analyzer-simplify/simplify-complex-expression/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable +--variable-sensitivity r == 2 ^SIGNAL=0$ ^EXIT=6$ @@ -11,4 +11,4 @@ Checks for a bug that occurred while changing the simplifier, where a variable would be replaced by the RHS of its last assignment, even if the value of that expression had changed since then; Most egregiously when the RHS contained the symbol on the LHS (thus leading -to a recursive definition). \ No newline at end of file +to a recursive definition). diff --git a/regression/goto-analyzer-simplify/simplify-lhs-array-index/test.desc b/regression/goto-analyzer-simplify/simplify-lhs-array-index/test.desc index f5a352cbd09..8ce04ba76ef 100644 --- a/regression/goto-analyzer-simplify/simplify-lhs-array-index/test.desc +++ b/regression/goto-analyzer-simplify/simplify-lhs-array-index/test.desc @@ -1,6 +1,6 @@ CORE main.c -"--variable --arrays" +"--variable-sensitivity --vsd-arrays" arr\[0l\] = arr\[1l\] = diff --git a/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/test.desc b/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/test.desc index 8e3526b73e5..4129ec58d45 100644 --- a/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/test.desc +++ b/regression/goto-analyzer-simplify/simplify-lhs-array-pointers-index/test.desc @@ -1,6 +1,6 @@ CORE main.c -"--variable --arrays --pointers" +"--variable-sensitivity --vsd-arrays --vsd-pointers" symbol_a = 1 symbol_b = 2 diff --git a/regression/goto-analyzer-simplify/simplify-lhs-dereference/test.desc b/regression/goto-analyzer-simplify/simplify-lhs-dereference/test.desc index 8fcfb8fce7d..bc05dc76913 100644 --- a/regression/goto-analyzer-simplify/simplify-lhs-dereference/test.desc +++ b/regression/goto-analyzer-simplify/simplify-lhs-dereference/test.desc @@ -1,6 +1,6 @@ CORE main.c -"--variable --pointers" +"--variable-sensitivity --vsd-pointers" symbol = 5 \*pointer = 6 diff --git a/regression/goto-analyzer-simplify/simplify-lhs-member/test.desc b/regression/goto-analyzer-simplify/simplify-lhs-member/test.desc index be66617cabb..ea66f6e269a 100644 --- a/regression/goto-analyzer-simplify/simplify-lhs-member/test.desc +++ b/regression/goto-analyzer-simplify/simplify-lhs-member/test.desc @@ -1,6 +1,6 @@ CORE main.c -"--variable --arrays --pointers --structs" +"--variable-sensitivity --vsd-arrays --vsd-pointers --vsd-structs" symbol = 5 \*value\.pointer_component = 6 diff --git a/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/test.desc b/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/test.desc index 00a90ef4e9d..c2903b287f7 100644 --- a/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/test.desc +++ b/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/test.desc @@ -1,6 +1,6 @@ CORE main.c -"--variable --arrays --pointers" +"--variable-sensitivity --vsd-arrays --vsd-pointers" array\[0l\] = 5 array\[\(signed long int\)nondet\] = 6 new_array\[1l\] = 7 diff --git a/regression/goto-analyzer-simplify/simplify-multiply-by-zero/test.desc b/regression/goto-analyzer-simplify/simplify-multiply-by-zero/test.desc index 6262cbd7d01..6675045b32a 100644 --- a/regression/goto-analyzer-simplify/simplify-multiply-by-zero/test.desc +++ b/regression/goto-analyzer-simplify/simplify-multiply-by-zero/test.desc @@ -1,6 +1,6 @@ CORE main.c -"--variable" +"--variable-sensitivity" ^SIGNAL=0$ ^EXIT=6$ main#return_value = 0; diff --git a/regression/goto-analyzer/constant_assertions_01/test.desc b/regression/goto-analyzer/constant_assertions_01/test.desc index 94fecb61f05..0692e81292f 100644 --- a/regression/goto-analyzer/constant_assertions_01/test.desc +++ b/regression/goto-analyzer/constant_assertions_01/test.desc @@ -1,6 +1,6 @@ CORE main.c ---verify --variable +--verify --variable-sensitivity ^\[main.assertion.1\] line 10 0: FAILURE \(if reachable\)$ ^\[main.assertion.2\] line 11 0 && 1: FAILURE \(if reachable\)$ ^\[main.assertion.3\] line 12 0 || 0: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_assertions_02/test.desc b/regression/goto-analyzer/constant_assertions_02/test.desc index 8f7f77cfc7f..851893237f4 100644 --- a/regression/goto-analyzer/constant_assertions_02/test.desc +++ b/regression/goto-analyzer/constant_assertions_02/test.desc @@ -1,6 +1,6 @@ CORE main.c ---verify --variable +--verify --variable-sensitivity ^\[main\.assertion\.1\] line 10 1: SUCCESS ^\[main\.assertion\.2\] line 11 0 || 1: SUCCESS ^\[main\.assertion\.3\] line 12 1 && 1: SUCCESS diff --git a/regression/goto-analyzer/constant_propagation_01/test-vsd.desc b/regression/goto-analyzer/constant_propagation_01/test-vsd.desc index 64b7bbafd9b..a857ab86251 100644 --- a/regression/goto-analyzer/constant_propagation_01/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_01/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --simplify out.gb +--variable-sensitivity --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_02/test-vsd.desc b/regression/goto-analyzer/constant_propagation_02/test-vsd.desc index 3aadc11a5f3..1b81e99291d 100644 --- a/regression/goto-analyzer/constant_propagation_02/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_02/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --simplify out.gb +--variable-sensitivity --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 9, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_03/test-vsd.desc b/regression/goto-analyzer/constant_propagation_03/test-vsd.desc index 3aadc11a5f3..1b81e99291d 100644 --- a/regression/goto-analyzer/constant_propagation_03/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_03/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --simplify out.gb +--variable-sensitivity --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 9, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_04/test-vsd.desc b/regression/goto-analyzer/constant_propagation_04/test-vsd.desc index 3aadc11a5f3..1b81e99291d 100644 --- a/regression/goto-analyzer/constant_propagation_04/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_04/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --simplify out.gb +--variable-sensitivity --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 9, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_05/test-vsd.desc b/regression/goto-analyzer/constant_propagation_05/test-vsd.desc index f608823f827..a8d6ab67685 100644 --- a/regression/goto-analyzer/constant_propagation_05/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_05/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] .* j!=3: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_06/test-vsd.desc b/regression/goto-analyzer/constant_propagation_06/test-vsd.desc index ac2aec727c4..6d9a2758650 100644 --- a/regression/goto-analyzer/constant_propagation_06/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_06/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* i\s*<\s*51: UNKNOWN$ diff --git a/regression/goto-analyzer/constant_propagation_07/test-vsd.desc b/regression/goto-analyzer/constant_propagation_07/test-vsd.desc index be8ad04d5a6..af5a39dfff6 100644 --- a/regression/goto-analyzer/constant_propagation_07/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_07/test-vsd.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---variable --simplify out.gb +--variable-sensitivity --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 3, assigns: 14, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_08/test-vsd.desc b/regression/goto-analyzer/constant_propagation_08/test-vsd.desc index 4b10f41e952..9138509c85b 100644 --- a/regression/goto-analyzer/constant_propagation_08/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_08/test-vsd.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---variable --arrays --simplify out.gb +--variable-sensitivity --vsd-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_08/test.desc b/regression/goto-analyzer/constant_propagation_08/test.desc index beddc104b13..082b3d1f98e 100644 --- a/regression/goto-analyzer/constant_propagation_08/test.desc +++ b/regression/goto-analyzer/constant_propagation_08/test.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---constants --arrays --simplify out.gb +--constants --vsd-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-vsd.desc b/regression/goto-analyzer/constant_propagation_09/test-vsd.desc index efd54ca17aa..50f80a45a22 100644 --- a/regression/goto-analyzer/constant_propagation_09/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_09/test-vsd.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---variable --arrays --verify +--variable-sensitivity --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 0: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_09/test.desc b/regression/goto-analyzer/constant_propagation_09/test.desc index fd4f0be0e61..7ac2fa210db 100644 --- a/regression/goto-analyzer/constant_propagation_09/test.desc +++ b/regression/goto-analyzer/constant_propagation_09/test.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---constants --arrays --verify +--constants --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 0: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_10/test-vsd.desc b/regression/goto-analyzer/constant_propagation_10/test-vsd.desc index fcc7a098b29..202eec092cd 100644 --- a/regression/goto-analyzer/constant_propagation_10/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_10/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --arrays --verify +--variable-sensitivity --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] line 10 a\[0\]==2: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_10/test.desc b/regression/goto-analyzer/constant_propagation_10/test.desc index 0728aedc43a..f2f41ac1a68 100644 --- a/regression/goto-analyzer/constant_propagation_10/test.desc +++ b/regression/goto-analyzer/constant_propagation_10/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --arrays --verify +--constants --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] line 10 a\[0\]==2: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_11/test-vsd.desc b/regression/goto-analyzer/constant_propagation_11/test-vsd.desc index 2c21db37186..29149ecf8d8 100644 --- a/regression/goto-analyzer/constant_propagation_11/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_11/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --arrays --simplify out.gb +--variable-sensitivity --vsd-arrays --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 7, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_11/test.desc b/regression/goto-analyzer/constant_propagation_11/test.desc index 08aa42f8422..07dfbcddacd 100644 --- a/regression/goto-analyzer/constant_propagation_11/test.desc +++ b/regression/goto-analyzer/constant_propagation_11/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --arrays --simplify out.gb +--constants --vsd-arrays --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 7, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_12/test-vsd.desc b/regression/goto-analyzer/constant_propagation_12/test-vsd.desc index de6f32ba004..89abc403bf5 100644 --- a/regression/goto-analyzer/constant_propagation_12/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_12/test-vsd.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---variable --simplify out.gb +--variable-sensitivity --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ ^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ diff --git a/regression/goto-analyzer/constant_propagation_13/test-vsd.desc b/regression/goto-analyzer/constant_propagation_13/test-vsd.desc index 8ced11a1357..ba3e0e23577 100644 --- a/regression/goto-analyzer/constant_propagation_13/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_13/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] .* y==0: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_14/test-vsd.desc b/regression/goto-analyzer/constant_propagation_14/test-vsd.desc index 6a3a4b25fd6..cfab18921ef 100644 --- a/regression/goto-analyzer/constant_propagation_14/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_14/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --arrays --verify +--variable-sensitivity --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ \[main\.assertion\.1\] .* a\[0\]==1 || a\[0\]==2: SUCCESS$ diff --git a/regression/goto-analyzer/constant_propagation_14/test.desc b/regression/goto-analyzer/constant_propagation_14/test.desc index 374af7d45e5..1e39bdc2119 100644 --- a/regression/goto-analyzer/constant_propagation_14/test.desc +++ b/regression/goto-analyzer/constant_propagation_14/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --arrays --verify +--constants --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ \[main\.assertion\.1\] .* a\[0\]==1 || a\[0\]==2: SUCCESS$ diff --git a/regression/goto-analyzer/constant_propagation_15/test-vsd.desc b/regression/goto-analyzer/constant_propagation_15/test-vsd.desc index 4aafae8319e..4a463c2811a 100644 --- a/regression/goto-analyzer/constant_propagation_15/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_15/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --arrays --verify +--variable-sensitivity --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] .* a\[0\]==2: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_15/test.desc b/regression/goto-analyzer/constant_propagation_15/test.desc index 5a2438aedc2..8bea9faf0b0 100644 --- a/regression/goto-analyzer/constant_propagation_15/test.desc +++ b/regression/goto-analyzer/constant_propagation_15/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --arrays --verify +--constants --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] .* a\[0\]==2: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_16/test-vsd.desc b/regression/goto-analyzer/constant_propagation_16/test-vsd.desc index f2d74c835aa..e8bc7e6b3c7 100644 --- a/regression/goto-analyzer/constant_propagation_16/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_16/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---show --variable +--show --variable-sensitivity ^EXIT=0$ ^SIGNAL=0$ -- diff --git a/regression/goto-analyzer/constant_propagation_17/test-vsd.desc b/regression/goto-analyzer/constant_propagation_17/test-vsd.desc index a4a7c537e4a..a3599c9d0fb 100644 --- a/regression/goto-analyzer/constant_propagation_17/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_17/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] .* i\s*<\s*51: (UNKNOWN|FAILURE \(if reachable\))$ diff --git a/regression/goto-analyzer/constant_propagation_18/test-vsd.desc b/regression/goto-analyzer/constant_propagation_18/test-vsd.desc index 9a6265af079..367e07e212f 100644 --- a/regression/goto-analyzer/constant_propagation_18/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_18/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 7 assertion \*p == 1: SUCCESS$ diff --git a/regression/goto-analyzer/constant_propagation_19/test-vsd.desc b/regression/goto-analyzer/constant_propagation_19/test-vsd.desc index f5f4fee881b..e7b84ee327e 100644 --- a/regression/goto-analyzer/constant_propagation_19/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_19/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 8 assertion x == 42: SUCCESS$ 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 8b39662488f..b8834858e4c 100644 --- a/regression/goto-analyzer/minimal-reproducer-for-struct-problem/test.desc +++ b/regression/goto-analyzer/minimal-reproducer-for-struct-problem/test.desc @@ -1,6 +1,6 @@ CORE minimal_reproducer_for_struct_problem.c ---variable --structs --verify +--variable-sensitivity --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 13 x.a==0: SUCCESS$ diff --git a/regression/goto-analyzer/sensitivity-function-call-array/test.desc b/regression/goto-analyzer/sensitivity-function-call-array/test.desc index a18b9d26b11..8a9bdded1e5 100644 --- a/regression/goto-analyzer/sensitivity-function-call-array/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-array/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --pointers --arrays --structs --verify +--variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] line 12 assertion \*arr_y==2: SUCCESS$ diff --git a/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc b/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc index fc6ff19a7e2..dd02bfd31fe 100644 --- a/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --pointers --arrays --structs --verify +--variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] line 16 assertion x==3: SUCCESS$ diff --git a/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc b/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc index 3f51c709a16..d598862c9e3 100644 --- a/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --pointers --arrays --structs --verify +--variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] line 11 assertion y==5: SUCCESS$ diff --git a/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc b/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc index f96f9fd17ed..68493c0dec4 100644 --- a/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --pointers --arrays --structs --verify +--variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[bar\.assertion\.1\] line 5 assertion other==4: SUCCESS$ diff --git a/regression/goto-analyzer/sensitivity-function-call-recursive/test.desc b/regression/goto-analyzer/sensitivity-function-call-recursive/test.desc index 2bb1b2580e8..8c4ef982cec 100644 --- a/regression/goto-analyzer/sensitivity-function-call-recursive/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-recursive/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --pointers --arrays --structs --verify +--variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] .* assertion y==4: UNKNOWN$ diff --git a/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc b/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc index ed8255be9f7..e36863269d5 100644 --- a/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --pointers --arrays --structs --verify +--variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] line 22 assertion y==6: UNKNOWN$ diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc index 69735a3a3b2..dbe314cf20f 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_dependency_arrays.c ---variable --arrays --pointers --structs --show +--variable-sensitivity --vsd-arrays --vsd-pointers --vsd-structs --show // Enable multi-line checking activate-multi-line-match ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc index 6656d3cbccc..febd1e06be0 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_dependency_pointers.c ---variable --arrays --pointers --structs --show +--variable-sensitivity --vsd-arrays --vsd-pointers --vsd-structs --show // Enable multi-line checking activate-multi-line-match ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc index 7be8d8a35ca..9b8b89de92a 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_dependency_structs.c ---variable --arrays --pointers --structs --show +--variable-sensitivity --vsd-arrays --vsd-pointers --vsd-structs --show // Enable multi-line checking activate-multi-line-match ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc index cb85440f564..f8ac0d87e84 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_dependency_variables.c ---variable --arrays --pointers --structs --show +--variable-sensitivity --vsd-arrays --vsd-pointers --vsd-structs --show ^EXIT=0$ ^SIGNAL=0$ main#return_value \(\) -> TOP @ \[1\] diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc index 34f32f40a5d..13718d11267 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --arrays --verify +--variable-sensitivity --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 11 array\[0\] == 5: UNKNOWN$ 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 34a40e94989..7961c6e1129 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,6 +1,6 @@ CORE sensitivity_test_constants_array_of_constants_array.c ---variable --arrays --verify --pointers +--variable-sensitivity --vsd-arrays --verify --vsd-pointers ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* a\[1\]\[2\]==0: SUCCESS$ 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 63f296b58bf..2a3a51682d4 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,6 +1,6 @@ CORE sensitivity_test_constants_array_of_constants_pointer.c ---variable --arrays --pointers --verify +--variable-sensitivity --vsd-arrays --vsd-pointers --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* a\[1\]==&a0: SUCCESS$ 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 de16c370dd5..39ca55caf4e 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,6 +1,6 @@ CORE sensitivity_test_constants_array_of_two_value_pointer.c ---variable --arrays --verify +--variable-sensitivity --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* a\[1\]==&a0: UNKNOWN$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array/test.desc index f3159eda917..8689736d76e 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_test_constants_array.c ---variable --arrays --verify --pointers +--variable-sensitivity --vsd-arrays --verify --vsd-pointers ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* a\[1\]==0: SUCCESS$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-char/test.desc b/regression/goto-analyzer/sensitivity-test-constants-char/test.desc index 3e0e11855ad..b5e8dc61dd2 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-char/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-char/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_test_constants_char.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x=='a': SUCCESS$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-float/test.desc b/regression/goto-analyzer/sensitivity-test-constants-float/test.desc index 72c3b69b398..03aca800b8c 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-float/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-float/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_test_constants_float.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x==0.0: SUCCESS$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-int/test.desc b/regression/goto-analyzer/sensitivity-test-constants-int/test.desc index 4a7b276b621..83c3f7bc565 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-int/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-int/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_test_constants_int.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x==0: SUCCESS$ 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 cc33c98ab65..cb8b1fc0385 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,6 +1,6 @@ CORE sensitivity_test_constants_pointer_to_constants_array.c ---variable --pointers --arrays --verify +--variable-sensitivity --vsd-pointers --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* p==&a\[0\]: SUCCESS$ 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 88f85ae3a7a..4d60991a5f3 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,6 +1,6 @@ CORE sensitivity_test_constants_pointer_to_constants_pointer.c ---variable --pointers --verify +--variable-sensitivity --vsd-pointers --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* \*\*x==0: SUCCESS$ 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 2f5839853c5..c573d6f5438 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 @@ -1,6 +1,6 @@ CORE sensitivity_test_constants_pointer_to_constants_struct.c ---variable --pointers --structs --verify +--variable-sensitivity --vsd-pointers --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] .* \(\*p\).a==0: SUCCESS$ 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 c3645e2e7d7..d099fabd811 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,6 +1,6 @@ CORE sensitivity_test_constants_pointer_to_two_value_array.c ---variable --pointers --verify +--variable-sensitivity --vsd-pointers --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* p==&a\[0\]: SUCCESS$ 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 359264c686d..890b32ec30c 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,6 +1,6 @@ CORE sensitivity_test_constants_pointer_to_two_value_struct.c ---variable --pointers --verify +--variable-sensitivity --vsd-pointers --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* \(\*p\).a==0: UNKNOWN$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc index 18f34a8836d..c9d705b1faf 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_test_constants_pointer.c ---variable --pointers --verify +--variable-sensitivity --vsd-pointers --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x==&a: SUCCESS$ 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 4634e6ec09b..133606bab62 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,6 +1,6 @@ CORE sensitivity_test_constants_struct_of_constants_array.c ---variable --structs --arrays --verify +--variable-sensitivity --vsd-structs --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x.a\[0\]==0: SUCCESS$ 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 cea1535c673..21b5a2d5d1a 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,6 +1,6 @@ CORE sensitivity_test_constants_struct_of_constants_pointer.c ---variable --structs --pointers --verify +--variable-sensitivity --vsd-structs --vsd-pointers --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x.a==&a1: SUCCESS$ 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 322edb6dfc3..b1022a4e455 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,6 +1,6 @@ CORE sensitivity_test_constants_struct_of_constants_struct.c ---variable --structs --verify +--variable-sensitivity --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x.s1.a==0: SUCCESS$ 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 52b5a18d808..3b131b882ba 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,6 +1,6 @@ CORE sensitivity_test_constants_struct_of_two_value_array.c ---variable --structs --verify +--variable-sensitivity --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x.a\[0\]==0: UNKNOWN$ 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 fb7559001b3..fa9989d07f5 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,6 +1,6 @@ CORE sensitivity_test_constants_struct_of_two_value_pointer.c ---variable --structs --verify +--variable-sensitivity --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x.a==&a1: UNKNOWN$ diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc index 35f225a3983..ca84cffa314 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_test_constants_struct.c ---variable --structs --verify +--variable-sensitivity --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x.a==0: SUCCESS$ diff --git a/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc b/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc index 9018d894ea3..ba1d75f316a 100644 --- a/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc +++ b/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc @@ -1,6 +1,6 @@ CORE data-dependency-context.c ---variable --structs --arrays --data-dependencies --show +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-data-dependencies --show // Enable multi-line checking activate-multi-line-match ^EXIT=0$ diff --git a/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc b/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc index 9e4cb0a0d34..38bc9ab0b1c 100644 --- a/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc +++ b/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc @@ -1,6 +1,6 @@ CORE struct-initialization.c ---variable --structs --verify +--variable-sensitivity --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] line 27 los.a==0: SUCCESS$ 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 d7de65f884a..8b6844fc44e 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,6 +1,6 @@ CORE sensitivity_test_two_value_array_of_two_value_array.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* a\[1\]\[2\]==0: UNKNOWN$ 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 6be850ffdb0..b1f64ea2215 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,6 +1,6 @@ CORE sensitivity_test_two_value_array_of_two_value_pointer.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* a\[1\]==&a0: UNKNOWN$ 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 8f4ab1fe304..badda851b39 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-array/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-array/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_test_two_value_array.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* a\[1\]==0: UNKNOWN$ 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 c2628bc33ab..2e5544cb994 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,6 +1,6 @@ CORE sensitivity_test_two_value_pointer_to_two_value_array.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] .* p==&a\[0\]: UNKNOWN$ 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 d610089530a..0cab798c26f 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,6 +1,6 @@ CORE sensitivity_test_two_value_pointer_to_two_value_pointer.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* \*\*x==0: UNKNOWN$ 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 65edb0a87ed..013ff96d085 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,6 +1,6 @@ CORE sensitivity_test_two_value_pointer_to_two_value_struct.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* \(\*p\).a==0: UNKNOWN$ 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 400fe99e372..ba2ce783e65 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_test_two_value_pointer.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] .* x==&a: UNKNOWN$ 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 ef99fb84bcc..ce077813a27 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,6 +1,6 @@ CORE sensitivity_test_two_value_struct_of_two_value_array.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x.a\[0\]==0: UNKNOWN$ 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 9454d040cf6..4180765e734 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,6 +1,6 @@ CORE sensitivity_test_two_value_struct_of_two_value_pointer.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x.a==&a1: UNKNOWN$ 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 42c36b7a063..6d412839f2f 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,6 +1,6 @@ CORE sensitivity_test_two_value_struct_of_two_value_struct.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x.s1.a==0: UNKNOWN$ 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 7193029cb7b..544aa1a6656 100644 --- a/regression/goto-analyzer/sensitivity-test-two-value-struct/test.desc +++ b/regression/goto-analyzer/sensitivity-test-two-value-struct/test.desc @@ -1,6 +1,6 @@ CORE sensitivity_test_two_value_struct.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] .* x.a==0: UNKNOWN$ diff --git a/regression/goto-analyzer/unreachable_assertions_01/test.desc b/regression/goto-analyzer/unreachable_assertions_01/test.desc index 7aad7cbf696..7bbc197986e 100644 --- a/regression/goto-analyzer/unreachable_assertions_01/test.desc +++ b/regression/goto-analyzer/unreachable_assertions_01/test.desc @@ -1,6 +1,6 @@ CORE main.c ---verify --variable +--verify --variable-sensitivity ^\[main\.assertion\.1\] line 13 0: SUCCESS \(unreachable\)$ ^\[main\.assertion\.2\] line 16 1: SUCCESS \(unreachable\)$ ^\[main\.assertion\.3\] line 19 x == y: SUCCESS \(unreachable\)$ diff --git a/regression/goto-analyzer/value-set-function-pointers-arrays/test.desc b/regression/goto-analyzer/value-set-function-pointers-arrays/test.desc index 4caa368fd04..fbcfd4e0cf5 100644 --- a/regression/goto-analyzer/value-set-function-pointers-arrays/test.desc +++ b/regression/goto-analyzer/value-set-function-pointers-arrays/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --structs --arrays --pointers --value-set --show --pointer-check +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --vsd-value-sets --show --pointer-check ^file main.c line 29 function main: replacing function pointer by 2 possible targets$ ^file main.c line 40 function main: replacing function pointer by 2 possible targets$ ^main::1::fun1 \(\) -> value-set-begin: ptr ->\([fg]\), ptr ->\([fg]\), :value-set-end$ diff --git a/regression/goto-analyzer/value-set-function-pointers-incremented/test.desc b/regression/goto-analyzer/value-set-function-pointers-incremented/test.desc index a675596f194..57e14147e00 100644 --- a/regression/goto-analyzer/value-set-function-pointers-incremented/test.desc +++ b/regression/goto-analyzer/value-set-function-pointers-incremented/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --structs --arrays --pointers --value-set --show --pointer-check +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --vsd-value-sets --show --pointer-check ^file main.c line 28 function main: replacing function pointer by 2 possible targets$ ^main::1::fun_incremented_show \(\) -> TOP$ ^EXIT=0$ diff --git a/regression/goto-analyzer/value-set-function-pointers-simple/test.desc b/regression/goto-analyzer/value-set-function-pointers-simple/test.desc index 406e42cf511..42cf759016d 100644 --- a/regression/goto-analyzer/value-set-function-pointers-simple/test.desc +++ b/regression/goto-analyzer/value-set-function-pointers-simple/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --structs --arrays --pointers --value-set --show --pointer-check +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --vsd-value-sets --show --pointer-check ^file main.c line 25 function main: replacing function pointer by 2 possible targets$ ^file main.c line 28 function main: replacing function pointer by 2 possible targets$ ^file main.c line 33 function main: replacing function pointer by 2 possible targets$ diff --git a/regression/goto-analyzer/value-set-function-pointers-structs/test.desc b/regression/goto-analyzer/value-set-function-pointers-structs/test.desc index b931818ac3b..b568837d705 100644 --- a/regression/goto-analyzer/value-set-function-pointers-structs/test.desc +++ b/regression/goto-analyzer/value-set-function-pointers-structs/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --structs --arrays --pointers --value-set --show --pointer-check +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --vsd-value-sets --show --pointer-check ^file main.c line 38 function main: replacing function pointer by 2 possible targets$ ^file main.c line 46 function main: replacing function pointer by 2 possible targets$ ^file main.c line 54 function main: replacing function pointer by 2 possible targets$ diff --git a/regression/goto-analyzer/value-set-simple/test_show.desc b/regression/goto-analyzer/value-set-simple/test_show.desc index a4e02531879..592aca1bc00 100644 --- a/regression/goto-analyzer/value-set-simple/test_show.desc +++ b/regression/goto-analyzer/value-set-simple/test_show.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --structs --arrays --pointers --value-set --show --pointer-check +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --vsd-value-sets --show --pointer-check ^global_int_show \(\) -> value-set-begin: [12], [12], :value-set-end$ ^main::1::local_double_show \(\) -> value-set-begin: [12]\.0, [12]\.0, :value-set-end$ ^main::1::local_double_ptr_show \(\) -> value-set-begin: ptr ->\(main::1::d[12]\), ptr ->\(main::1::d[12]\), :value-set-end$ diff --git a/regression/goto-analyzer/value-set-simple/test_verify.desc b/regression/goto-analyzer/value-set-simple/test_verify.desc index 0ac106b6fbb..c4c3bf6a647 100644 --- a/regression/goto-analyzer/value-set-simple/test_verify.desc +++ b/regression/goto-analyzer/value-set-simple/test_verify.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---variable --structs --arrays --pointers --value-set --verify --pointer-check +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --vsd-value-sets --verify --pointer-check ^\[main.assertion.1\] line 16 assertion global_int == 2: UNKNOWN$ ^\[main.assertion.2\] line 17 assertion global_int == 1 \|\| global_int == 2: SUCCESS$ ^\[main.assertion.3\] line 18 assertion global_int > 0: SUCCESS$ diff --git a/regression/goto-analyzer/value-set-structs/test_show.desc b/regression/goto-analyzer/value-set-structs/test_show.desc index a3533ea2449..68001656a3a 100644 --- a/regression/goto-analyzer/value-set-structs/test_show.desc +++ b/regression/goto-analyzer/value-set-structs/test_show.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --structs --arrays --pointers --value-set --show --pointer-check +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --vsd-value-sets --show --pointer-check activate-multi-line-match main::1::s_show \(\) -> \{\.d=value-set-begin: [12]\.0, [12]\.0, :value-set-end, \.str=\{\[0\] = value-set-begin: '[xy]', '[xy]', :value-set-end\n\[1\] = value-set-begin: '\\n', :value-set-end main::1::u_show \(\) -> \{\.d=value-set-begin: [123]\.0, [123].0, [123]\.0, :value-set-end, \.str=\{\[0\] = value-set-begin: '[xyz]', '[xyz]', '[xyz]', :value-set-end\n\[1\] = value-set-begin: '\\n', :value-set-end diff --git a/regression/goto-analyzer/value-set-structs/test_verify.desc b/regression/goto-analyzer/value-set-structs/test_verify.desc index 5833417dd35..8aeaa4c90b5 100644 --- a/regression/goto-analyzer/value-set-structs/test_verify.desc +++ b/regression/goto-analyzer/value-set-structs/test_verify.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---variable --structs --arrays --pointers --value-set --verify --pointer-check +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --vsd-value-sets --verify --pointer-check ^\[main\.assertion\.1\] line 33 assertion s\.i == 0: UNKNOWN$ ^\[main\.assertion\.2\] line 35 assertion s\.d == 1.0: UNKNOWN$ ^\[main\.assertion\.3\] line 36 assertion s\.d == 1.0 \|\| s.d == 2.0: SUCCESS$ diff --git a/regression/goto-analyzer/variable-sensitivity-annihiliator-test/test.desc b/regression/goto-analyzer/variable-sensitivity-annihiliator-test/test.desc index 4abfae4a5cb..c935c4d26ca 100644 --- a/regression/goto-analyzer/variable-sensitivity-annihiliator-test/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-annihiliator-test/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --pointers --arrays --structs --unreachable-instructions +--variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --unreachable-instructions ^EXIT=0$ ^SIGNAL=0$ line 18 function func diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc index fdef4497fa1..620a8f713d0 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-array/test.desc @@ -1,6 +1,6 @@ CORE main.c ---function pass_param --variable --pointers --arrays --structs --verify +--function pass_param --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ \[pass_param\.assertion\.1\] line 13 b\[0\]==0: SUCCESS diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc index 57435da1a68..3dfcbcb927c 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc @@ -1,6 +1,6 @@ CORE main.c ---function test_param_function --variable --pointers --arrays --structs --verify +--function test_param_function --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ \[test_param_function.assertion\.1\] line 15 a==5: SUCCESS diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/test.desc index 2f659f02b22..5983fafc9c7 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-non-terminating-function/test.desc @@ -1,6 +1,6 @@ CORE main.c ---function test_non_terminating --variable --pointers --arrays --structs --verify +--function test_non_terminating --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ \[test_non_terminating.assertion\.1\] line 23 one_val==5: SUCCESS diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc index 3e43bb8f38a..959a2dd1562 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc @@ -1,6 +1,6 @@ CORE main.c ---function pointer_test --variable --pointers --arrays --structs --verify +--function pointer_test --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[pointer_test.assertion\.1\] line 41 j==1: SUCCESS$ diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc index ffbac31223a..5f0d24e90bd 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc @@ -1,6 +1,6 @@ CORE main.c ---function simple_test --variable --pointers --arrays --structs --verify +--function simple_test --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[simple_test\.assertion\.1\] line 25 i==0: SUCCESS$ diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc index fdbc292e024..2414be0a86a 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc @@ -1,6 +1,6 @@ CORE main.c ---function global_test --variable --pointers --arrays --structs --verify +--function global_test --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[global_test\.assertion\.1\] line 67 global==42: SUCCESS$ diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc index a0107fef2fb..c9c02c43753 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc @@ -1,6 +1,6 @@ CORE main.c ---function pass_param --variable --pointers --arrays --structs --verify +--function pass_param --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ ^\[pass_param\.assertion\.1\] line 25 human_instance.age==24: SUCCESS$ diff --git a/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc b/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc index 110a280ee8b..b08db01e7a7 100644 --- a/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc @@ -1,6 +1,6 @@ CORE main.c ---function main --variable --structs --verify +--function main --variable-sensitivity --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ \[main\.assertion\.1\] line 12 bs\.byte==10: SUCCESS diff --git a/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc b/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc index f7974e65b0a..e23f825c23d 100644 --- a/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc @@ -1,6 +1,6 @@ CORE main.c ---function main --variable --structs --interval-values --verify +--function main --variable-sensitivity --vsd-structs --vsd-intervals --verify ^EXIT=0$ ^SIGNAL=0$ \[main\.assertion\.1\] line 12 bs\.byte==10: SUCCESS diff --git a/regression/goto-analyzer/variable-sensitivity-bug-01/test.desc b/regression/goto-analyzer/variable-sensitivity-bug-01/test.desc index d9fef3799bc..69e3f769a07 100644 --- a/regression/goto-analyzer/variable-sensitivity-bug-01/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-bug-01/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --structs --arrays --pointers --show +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --show ^EXIT=0$ ^SIGNAL=0$ -- diff --git a/regression/goto-analyzer/variable-sensitivity-bug-02/test.desc b/regression/goto-analyzer/variable-sensitivity-bug-02/test.desc index 15e070c2aa4..cefac4ef378 100644 --- a/regression/goto-analyzer/variable-sensitivity-bug-02/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-bug-02/test.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---variable-sensitivity --structs --arrays --pointers --show +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --show ^EXIT=0$ ^SIGNAL=0$ -- diff --git a/regression/goto-analyzer/variable-sensitivity-bug-03/test.desc b/regression/goto-analyzer/variable-sensitivity-bug-03/test.desc index 15e070c2aa4..cefac4ef378 100644 --- a/regression/goto-analyzer/variable-sensitivity-bug-03/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-bug-03/test.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---variable-sensitivity --structs --arrays --pointers --show +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --show ^EXIT=0$ ^SIGNAL=0$ -- diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc index 7b8fdc8233e..d14f1aa42db 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc @@ -1,6 +1,6 @@ CORE main.c ---dependence-graph-vs --structs --arrays --verify +--dependence-graph-vs --vsd-structs --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] line 20 s_str.idx > 1: UNKNOWN$ diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc index 7af73c46f2c..cd7f36370fb 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc @@ -1,6 +1,6 @@ CORE main.c -file1.c file2.c --dependence-graph-vs --structs --arrays --show +file1.c file2.c --dependence-graph-vs --vsd-structs --vsd-arrays --show ^EXIT=0$ ^SIGNAL=0$ Data dependencies: 58 \[st.a\] diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc index 60d786367b3..7970f84b12f 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc @@ -1,6 +1,6 @@ CORE main.c -file1.c file2.c --dependence-graph-vs --structs --arrays --show +file1.c file2.c --dependence-graph-vs --vsd-structs --vsd-arrays --show ^EXIT=0$ ^SIGNAL=0$ ^Data dependencies: 58 \[st.a\]$ diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc index cc082a54cac..da2322955fc 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc @@ -1,6 +1,6 @@ CORE main.c ---dependence-graph-vs --arrays --show +--dependence-graph-vs --vsd-arrays --show activate-multi-line-match ^EXIT=0$ ^SIGNAL=0$ diff --git a/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/test.desc b/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/test.desc index 9686aecf8bb..a6456a135d5 100644 --- a/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-floating-point-simplification/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable --verify +--variable-sensitivity --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion\.1\] line 12 assertion small_0_1 < big_0_1: SUCCESS diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/test.desc index ccf04bdc5e3..64eeff47b67 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-01/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --interval-values --show +--variable-sensitivity --vsd-intervals --show ^EXIT=0$ ^SIGNAL=0$ main::1::z \(\) -> \[3, 3\] @ \[5\] diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/test.desc index efc8c529e7b..0aa44fd1a9d 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-02/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --interval-values --show +--variable-sensitivity --vsd-intervals --show ^EXIT=0$ ^SIGNAL=0$ main::1::z \(\) -> \[3, 4\] @ \[9\] diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/test.desc index b231fd0f0b4..44ca7caa05e 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-arith-03/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --interval-values --show +--variable-sensitivity --vsd-intervals --show ^EXIT=0$ ^SIGNAL=0$ main::1::a \(\) -> \[6, 6\] @ \[7\] diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/test.desc index 7b9ae83393d..21de235a5b4 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-array-constant-access/test.desc @@ -1,6 +1,6 @@ CORE main.c ---show --variable-sensitivity --interval-values --arrays +--show --variable-sensitivity --vsd-intervals --vsd-arrays ^EXIT=0$ ^SIGNAL=0$ main::1::second_value \(\) -> \[2, 2\] @ \[3\] diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/test.desc index 738ea085c60..75c987273d7 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-array-interval-access/test.desc @@ -1,6 +1,6 @@ CORE main.c ---show --variable-sensitivity --interval-values --arrays +--show --variable-sensitivity --vsd-intervals --vsd-arrays ^EXIT=0$ ^SIGNAL=0$ main::1::arr_at_ix \(\) -> \[1, 3\] @ \[9\] diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc index 32d066eee9c..3d95482d9fe 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-complex-structures/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --interval-values --structs --pointers --show +--variable-sensitivity --vsd-intervals --vsd-structs --vsd-pointers --show ^EXIT=0$ ^SIGNAL=0$ main::1::vecMinusTenAndTen \(\) -> \{.x=\[FFFFFFF6, FFFFFFF6\] \@ \[3\], .y=\[A, A\] \@ \[3\]\} @ \[3\] diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-float/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-float/test.desc index 0fa2d53d8d6..42e4bdf0dda 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-float/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-float/test.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---variable-sensitivity --interval-values --show +--variable-sensitivity --vsd-intervals --show main::1::zero \(\) -> \[00000000000000000000000000000000, 00000000000000000000000000000000\] main::1::1::one \(\) -> \[00111111100000000000000000000000, 00111111100000000000000000000000\] main::1::2::minus_one \(\) -> \[10111111100000000000000000000000, 10111111100000000000000000000000\] diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc index 446f664a76c..cb215c854f6 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-logical-01/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --interval-values --show +--variable-sensitivity --vsd-intervals --show ^EXIT=0$ ^SIGNAL=0$ main::1::b1 \(\) -> \[1, 1\] @ \[2\] diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/test.desc index 1e09d532f7c..ba62f266d57 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-mixed-float-bool/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --interval-values --verify +--variable-sensitivity --vsd-intervals --verify \[main\.assertion\.1\] line 10 x > y, z == 1: SUCCESS \[main\.assertion\.2\] line 17 x < y, z == 1: SUCCESS ^EXIT=0$ diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/test.desc index 12e1dd0af21..607e9eea619 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values-multiplication/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --interval-values --show +--variable-sensitivity --vsd-intervals --show ^EXIT=0$ ^SIGNAL=0$ main::1::r \(\) -> TOP @ \[1\] diff --git a/regression/goto-analyzer/variable-sensitivity-interval-values/test.desc b/regression/goto-analyzer/variable-sensitivity-interval-values/test.desc index fd0a39db9f0..7c089db88b4 100644 --- a/regression/goto-analyzer/variable-sensitivity-interval-values/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-interval-values/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --interval-values --show +--variable-sensitivity --vsd-intervals --show ^EXIT=0$ ^SIGNAL=0$ main::1::zero \(\) -> \[0, 0\] @ \[3\] diff --git a/regression/goto-analyzer/write-stack-types/test.desc b/regression/goto-analyzer/write-stack-types/test.desc index d148b1ae7ef..d89557f46c6 100644 --- a/regression/goto-analyzer/write-stack-types/test.desc +++ b/regression/goto-analyzer/write-stack-types/test.desc @@ -1,6 +1,6 @@ CORE write-stack-address-of.c ---variable --structs --pointers --verify +--variable-sensitivity --vsd-structs --vsd-pointers --verify ^EXIT=0$ ^SIGNAL=0$ ^\[func1\.assertion\.1\] line 15 func1.a == 0: UNKNOWN$ From 8fe70c76e8fcb2ecb0fdd408bb2d75383a011fa9 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 17 Aug 2020 22:53:41 +0100 Subject: [PATCH 322/342] Re-enable dependency graph tests that were disabled at some point --- regression/goto-analyzer/dependence-graph10/test.desc | 2 +- regression/goto-analyzer/dependence-graph11/test.desc | 2 +- regression/goto-analyzer/dependence-graph12/test.desc | 2 +- regression/goto-analyzer/dependence-graph4/test.desc | 2 +- regression/goto-analyzer/dependence-graph7/test.desc | 2 +- regression/goto-analyzer/dependence-graph8/test.desc | 2 +- regression/goto-analyzer/dependence-graph9/test.desc | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/regression/goto-analyzer/dependence-graph10/test.desc b/regression/goto-analyzer/dependence-graph10/test.desc index 42ae3800a9b..26943fc2e68 100644 --- a/regression/goto-analyzer/dependence-graph10/test.desc +++ b/regression/goto-analyzer/dependence-graph10/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --dependence-graph --show activate-multi-line-match diff --git a/regression/goto-analyzer/dependence-graph11/test.desc b/regression/goto-analyzer/dependence-graph11/test.desc index d316a2e3f0d..32969498ac0 100644 --- a/regression/goto-analyzer/dependence-graph11/test.desc +++ b/regression/goto-analyzer/dependence-graph11/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --dependence-graph --show activate-multi-line-match diff --git a/regression/goto-analyzer/dependence-graph12/test.desc b/regression/goto-analyzer/dependence-graph12/test.desc index 6bd22947426..419f4efc4e1 100644 --- a/regression/goto-analyzer/dependence-graph12/test.desc +++ b/regression/goto-analyzer/dependence-graph12/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --dependence-graph --show activate-multi-line-match diff --git a/regression/goto-analyzer/dependence-graph4/test.desc b/regression/goto-analyzer/dependence-graph4/test.desc index 16a2d8905cc..670220ddf98 100644 --- a/regression/goto-analyzer/dependence-graph4/test.desc +++ b/regression/goto-analyzer/dependence-graph4/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --show --dependence-graph --text - activate-multi-line-match diff --git a/regression/goto-analyzer/dependence-graph7/test.desc b/regression/goto-analyzer/dependence-graph7/test.desc index 516c149ddaa..80a11db5a17 100644 --- a/regression/goto-analyzer/dependence-graph7/test.desc +++ b/regression/goto-analyzer/dependence-graph7/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --dependence-graph --show activate-multi-line-match diff --git a/regression/goto-analyzer/dependence-graph8/test.desc b/regression/goto-analyzer/dependence-graph8/test.desc index 7a62b6868c7..50a092d6d9e 100644 --- a/regression/goto-analyzer/dependence-graph8/test.desc +++ b/regression/goto-analyzer/dependence-graph8/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --dependence-graph --show activate-multi-line-match diff --git a/regression/goto-analyzer/dependence-graph9/test.desc b/regression/goto-analyzer/dependence-graph9/test.desc index ca075f63118..c6dd50d71cb 100644 --- a/regression/goto-analyzer/dependence-graph9/test.desc +++ b/regression/goto-analyzer/dependence-graph9/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --dependence-graph --show activate-multi-line-match From 88f7a74b20915e81da84e5200ab2f4206b9fe4a7 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 17 Aug 2020 23:44:21 +0100 Subject: [PATCH 323/342] Tidy up, fix and update the constant propagation tests (VSD and not) --- .../goto-analyzer/constant_propagation_07/test-vsd.desc | 6 +++--- regression/goto-analyzer/constant_propagation_07/test.desc | 2 +- .../goto-analyzer/constant_propagation_08/test-vsd.desc | 6 +++--- regression/goto-analyzer/constant_propagation_08/test.desc | 2 +- .../goto-analyzer/constant_propagation_09/test-vsd.desc | 4 ++-- regression/goto-analyzer/constant_propagation_09/test.desc | 6 +++--- regression/goto-analyzer/constant_propagation_10/test.desc | 2 +- .../goto-analyzer/constant_propagation_11/test-vsd.desc | 4 ++-- regression/goto-analyzer/constant_propagation_11/test.desc | 6 +++--- .../goto-analyzer/constant_propagation_12/test-vsd.desc | 2 +- regression/goto-analyzer/constant_propagation_12/test.desc | 2 +- regression/goto-analyzer/constant_propagation_14/test.desc | 2 +- regression/goto-analyzer/constant_propagation_15/test.desc | 2 +- .../goto-analyzer/constant_propagation_18/test-vsd.desc | 2 +- .../goto-analyzer/constant_propagation_19/test-vsd.desc | 2 +- 15 files changed, 25 insertions(+), 25 deletions(-) diff --git a/regression/goto-analyzer/constant_propagation_07/test-vsd.desc b/regression/goto-analyzer/constant_propagation_07/test-vsd.desc index af5a39dfff6..c313d50afe1 100644 --- a/regression/goto-analyzer/constant_propagation_07/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_07/test-vsd.desc @@ -1,9 +1,9 @@ -KNOWNBUG +CORE main.c --variable-sensitivity --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 3, assigns: 14, function calls: 0$ -^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 15, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 3, assigns: 10, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 19, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_07/test.desc b/regression/goto-analyzer/constant_propagation_07/test.desc index 0e6ee2c04ee..71416697fd4 100644 --- a/regression/goto-analyzer/constant_propagation_07/test.desc +++ b/regression/goto-analyzer/constant_propagation_07/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --constants --simplify out.gb ^EXIT=0$ diff --git a/regression/goto-analyzer/constant_propagation_08/test-vsd.desc b/regression/goto-analyzer/constant_propagation_08/test-vsd.desc index 9138509c85b..d2239d80583 100644 --- a/regression/goto-analyzer/constant_propagation_08/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_08/test-vsd.desc @@ -1,9 +1,9 @@ -KNOWNBUG +CORE main.c --variable-sensitivity --vsd-arrays --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: 2, assigns: 9, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 3, assigns: 18, 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 082b3d1f98e..52d013d15f5 100644 --- a/regression/goto-analyzer/constant_propagation_08/test.desc +++ b/regression/goto-analyzer/constant_propagation_08/test.desc @@ -1,6 +1,6 @@ KNOWNBUG main.c ---constants --vsd-arrays --simplify out.gb +--constants --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-vsd.desc b/regression/goto-analyzer/constant_propagation_09/test-vsd.desc index 50f80a45a22..810a5ef1d63 100644 --- a/regression/goto-analyzer/constant_propagation_09/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_09/test-vsd.desc @@ -1,8 +1,8 @@ -KNOWNBUG +CORE main.c --variable-sensitivity --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 0: FAILURE \(if reachable\)$ +^\[main.assertion.1\] line \d+ a\[0\]==0: FAILURE \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_09/test.desc b/regression/goto-analyzer/constant_propagation_09/test.desc index 7ac2fa210db..3edf55e5260 100644 --- a/regression/goto-analyzer/constant_propagation_09/test.desc +++ b/regression/goto-analyzer/constant_propagation_09/test.desc @@ -1,8 +1,8 @@ -KNOWNBUG +CORE main.c ---constants --vsd-arrays --verify +--constants --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 9 assertion a\[(\(signed( long)? long int\))?0\] == 0: FAILURE \(if reachable\)$ +^\[main.assertion.1\] line \d+ a\[0\]==0: FAILURE \(if reachable\)$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_10/test.desc b/regression/goto-analyzer/constant_propagation_10/test.desc index f2f41ac1a68..0caf5a98314 100644 --- a/regression/goto-analyzer/constant_propagation_10/test.desc +++ b/regression/goto-analyzer/constant_propagation_10/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --vsd-arrays --verify +--constants --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] line 10 a\[0\]==2: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_11/test-vsd.desc b/regression/goto-analyzer/constant_propagation_11/test-vsd.desc index 29149ecf8d8..57fde6c2fd6 100644 --- a/regression/goto-analyzer/constant_propagation_11/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_11/test-vsd.desc @@ -3,7 +3,7 @@ main.c --variable-sensitivity --vsd-arrays --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 1, assigns: 7, function calls: 0$ -^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 12, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 9, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 15, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_11/test.desc b/regression/goto-analyzer/constant_propagation_11/test.desc index 07dfbcddacd..e3e66e103ff 100644 --- a/regression/goto-analyzer/constant_propagation_11/test.desc +++ b/regression/goto-analyzer/constant_propagation_11/test.desc @@ -1,9 +1,9 @@ CORE main.c ---constants --vsd-arrays --simplify out.gb +--constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 1, assigns: 7, function calls: 0$ -^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 12, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 9, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 15, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_12/test-vsd.desc b/regression/goto-analyzer/constant_propagation_12/test-vsd.desc index 89abc403bf5..1ba76308b8d 100644 --- a/regression/goto-analyzer/constant_propagation_12/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_12/test-vsd.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --variable-sensitivity --simplify out.gb ^EXIT=0$ diff --git a/regression/goto-analyzer/constant_propagation_12/test.desc b/regression/goto-analyzer/constant_propagation_12/test.desc index 8900020b9b2..50879584471 100644 --- a/regression/goto-analyzer/constant_propagation_12/test.desc +++ b/regression/goto-analyzer/constant_propagation_12/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --constants --simplify out.gb ^EXIT=0$ diff --git a/regression/goto-analyzer/constant_propagation_14/test.desc b/regression/goto-analyzer/constant_propagation_14/test.desc index 1e39bdc2119..29453ed0c2c 100644 --- a/regression/goto-analyzer/constant_propagation_14/test.desc +++ b/regression/goto-analyzer/constant_propagation_14/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --vsd-arrays --verify +--constants --verify ^EXIT=0$ ^SIGNAL=0$ \[main\.assertion\.1\] .* 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 8bea9faf0b0..e16cf25d80b 100644 --- a/regression/goto-analyzer/constant_propagation_15/test.desc +++ b/regression/goto-analyzer/constant_propagation_15/test.desc @@ -1,6 +1,6 @@ CORE main.c ---constants --vsd-arrays --verify +--constants --verify ^EXIT=0$ ^SIGNAL=0$ ^\[main\.assertion\.1\] .* a\[0\]==2: FAILURE \(if reachable\)$ diff --git a/regression/goto-analyzer/constant_propagation_18/test-vsd.desc b/regression/goto-analyzer/constant_propagation_18/test-vsd.desc index 367e07e212f..604a018b834 100644 --- a/regression/goto-analyzer/constant_propagation_18/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_18/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --verify +--variable-sensitivity --verify --vsd-pointers ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 7 assertion \*p == 1: SUCCESS$ diff --git a/regression/goto-analyzer/constant_propagation_19/test-vsd.desc b/regression/goto-analyzer/constant_propagation_19/test-vsd.desc index e7b84ee327e..c18c3beb95b 100644 --- a/regression/goto-analyzer/constant_propagation_19/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_19/test-vsd.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --verify +--variable-sensitivity --verify --vsd-pointers ^EXIT=0$ ^SIGNAL=0$ ^\[main.assertion.1\] line 8 assertion x == 42: SUCCESS$ From 78b849e530af8a5990b6721d2042017987e773bd Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 18 Aug 2020 13:40:00 +0100 Subject: [PATCH 324/342] Make tests independent of the exact line numbers for assertions --- .../sensitivity-function-call-array/test.desc | 10 ++-- .../test.desc | 8 ++-- .../test.desc | 10 ++-- .../test.desc | 4 +- .../test.desc | 4 +- .../test.desc | 4 +- .../test.desc | 48 +++++++++---------- .../test.desc | 6 +-- .../test.desc | 4 +- .../test.desc | 16 +++---- .../test.desc | 4 +- .../test.desc | 4 +- .../test.desc | 2 +- .../goto-analyzer/write-stack-types/test.desc | 2 +- 14 files changed, 63 insertions(+), 63 deletions(-) diff --git a/regression/goto-analyzer/sensitivity-function-call-array/test.desc b/regression/goto-analyzer/sensitivity-function-call-array/test.desc index 8a9bdded1e5..8b33d4a540b 100644 --- a/regression/goto-analyzer/sensitivity-function-call-array/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-array/test.desc @@ -3,10 +3,10 @@ main.c --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] line 12 assertion \*arr_y==2: SUCCESS$ -^\[main\.assertion\.2\] line 15 assertion p2arr==arr_y: SUCCESS$ -^\[main\.assertion\.3\] line 16 assertion \*p2arr==2: SUCCESS$ -^\[bar\.assertion\.1\] line 22 assertion \*arr_unmodified==1: SUCCESS$ -^\[bar\.assertion\.2\] line 28 assertion \*arr_modified==2: SUCCESS$ +^\[main\.assertion\.1\] line \d+ assertion \*arr_y == 2: SUCCESS$ +^\[main\.assertion\.2\] line \d+ assertion p2arr == arr_y: SUCCESS$ +^\[main\.assertion\.3\] line \d+ assertion \*p2arr == 2: SUCCESS$ +^\[bar\.assertion\.1\] line \d+ assertion \*arr_unmodified == 1: SUCCESS$ +^\[bar\.assertion\.2\] line \d+ assertion \*arr_modified == 2: SUCCESS$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc b/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc index dd02bfd31fe..e2a521902af 100644 --- a/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-opaque/test.desc @@ -3,9 +3,9 @@ main.c --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] line 16 assertion x==3: SUCCESS$ -^\[main\.assertion\.2\] line 17 assertion y==4: UNKNOWN$ -^\[main\.assertion\.3\] line 18 assertion z==0: UNKNOWN$ -^\[main\.assertion\.4\] line 19 assertion global_value==4: UNKNOWN$ +^\[main\.assertion\.1\] line \d+ assertion x == 3: SUCCESS$ +^\[main\.assertion\.2\] line \d+ assertion y == 4: UNKNOWN$ +^\[main\.assertion\.3\] line \d+ assertion z == 0: UNKNOWN$ +^\[main\.assertion\.4\] line \d+ assertion global_value == 4: UNKNOWN$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc b/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc index d598862c9e3..d067eb420fe 100644 --- a/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-pointer/test.desc @@ -3,10 +3,10 @@ main.c --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] line 11 assertion y==5: SUCCESS$ -^\[main\.assertion\.2\] line 12 assertion p2x==&y: SUCCESS$ -^\[main\.assertion\.3\] line 13 assertion \*p2x==5: SUCCESS$ -^\[bar\.assertion\.1\] line 18 assertion \*unmodified==3: SUCCESS$ -^\[bar\.assertion\.2\] line 22 assertion \*modifed==5: SUCCESS$ +^\[main\.assertion\.1\] line \d+ assertion y == 5: SUCCESS$ +^\[main\.assertion\.2\] line \d+ assertion p2x == &y: SUCCESS$ +^\[main\.assertion\.3\] line \d+ assertion \*p2x == 5: SUCCESS$ +^\[bar\.assertion\.1\] line \d+ assertion \*unmodified == 3: SUCCESS$ +^\[bar\.assertion\.2\] line \d+ assertion \*modifed == 5: SUCCESS$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc b/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc index 68493c0dec4..39579c64cea 100644 --- a/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-primitive/test.desc @@ -3,7 +3,7 @@ main.c --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[bar\.assertion\.1\] line 5 assertion other==4: SUCCESS$ -^\[main\.assertion\.1\] line 13 assertion y==5: SUCCESS$ +^\[bar\.assertion\.1\] line \d+ assertion other == 4: SUCCESS$ +^\[main\.assertion\.1\] line \d+ assertion y == 5: SUCCESS$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc b/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc index e36863269d5..d7caf6fb09c 100644 --- a/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc +++ b/regression/goto-analyzer/sensitivity-function-call-varargs/test.desc @@ -3,7 +3,7 @@ main.c --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] line 22 assertion y==6: UNKNOWN$ -^\[main\.assertion\.2\] line 25 assertion z==0: UNKNOWN$ +^\[main\.assertion\.1\] line \d+ assertion y == 6: UNKNOWN$ +^\[main\.assertion\.2\] line \d+ assertion z == 0: UNKNOWN$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc index 13718d11267..5024310f764 100644 --- a/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc +++ b/regression/goto-analyzer/sensitivity-test-constants-array-loop/test.desc @@ -3,7 +3,7 @@ main.c --variable-sensitivity --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main.assertion.1\] line 11 array\[0\] == 5: UNKNOWN$ -^\[main.assertion.2\] line 12 array\[1\] == 5: UNKNOWN$ +^\[main.assertion.1\] line \d+ array\[0\] == 5: UNKNOWN$ +^\[main.assertion.2\] line \d+ array\[1\] == 5: UNKNOWN$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc b/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc index 38bc9ab0b1c..2ca2c036272 100644 --- a/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc +++ b/regression/goto-analyzer/sensitivity-test-struct-initialization/test.desc @@ -3,29 +3,29 @@ struct-initialization.c --variable-sensitivity --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] line 27 los.a==0: SUCCESS$ -^\[main\.assertion\.2\] line 28 los.b==0: SUCCESS$ -^\[main\.assertion\.3\] line 29 los2.a==3: SUCCESS$ -^\[main\.assertion\.4\] line 30 los2.b==4: SUCCESS$ -^\[main\.assertion\.5\] line 31 los3.a==3: SUCCESS$ -^\[main\.assertion\.6\] line 32 los3.b==4: SUCCESS$ -^\[main\.assertion\.7\] line 33 los4.a==3: SUCCESS$ -^\[main\.assertion\.8\] line 34 los4.b==0: SUCCESS$ -^\[main\.assertion\.9\] line 35 los5.a==0: SUCCESS$ -^\[main\.assertion\.10\] line 36 los5.b==4: SUCCESS$ -^\[main\.assertion\.11\] line 37 los6.a==3: SUCCESS$ -^\[main\.assertion\.12\] line 38 los6.b==4: SUCCESS$ -^\[main\.assertion\.13\] line 40 lus.a==0: SUCCESS$ -^\[main\.assertion\.14\] line 41 lus.b==0: SUCCESS$ -^\[main\.assertion\.15\] line 42 lus2.a==3: SUCCESS$ -^\[main\.assertion\.16\] line 43 lus2.b==4: SUCCESS$ -^\[main\.assertion\.17\] line 44 lus3.a==3: SUCCESS$ -^\[main\.assertion\.18\] line 45 lus3.b==4: SUCCESS$ -^\[main\.assertion\.19\] line 46 lus4.a==3: SUCCESS$ -^\[main\.assertion\.20\] line 47 lus4.b==0: SUCCESS$ -^\[main\.assertion\.21\] line 48 lus5.a==0: SUCCESS$ -^\[main\.assertion\.22\] line 49 lus5.b==4: SUCCESS$ -^\[main\.assertion\.23\] line 50 lus6.a==3: SUCCESS$ -^\[main\.assertion\.24\] line 51 lus6.b==4: SUCCESS$ +^\[main\.assertion\.1\] line \d+ los.a==0: SUCCESS$ +^\[main\.assertion\.2\] line \d+ los.b==0: SUCCESS$ +^\[main\.assertion\.3\] line \d+ los2.a==3: SUCCESS$ +^\[main\.assertion\.4\] line \d+ los2.b==4: SUCCESS$ +^\[main\.assertion\.5\] line \d+ los3.a==3: SUCCESS$ +^\[main\.assertion\.6\] line \d+ los3.b==4: SUCCESS$ +^\[main\.assertion\.7\] line \d+ los4.a==3: SUCCESS$ +^\[main\.assertion\.8\] line \d+ los4.b==0: SUCCESS$ +^\[main\.assertion\.9\] line \d+ los5.a==0: SUCCESS$ +^\[main\.assertion\.10\] line \d+ los5.b==4: SUCCESS$ +^\[main\.assertion\.11\] line \d+ los6.a==3: SUCCESS$ +^\[main\.assertion\.12\] line \d+ los6.b==4: SUCCESS$ +^\[main\.assertion\.13\] line \d+ lus.a==0: SUCCESS$ +^\[main\.assertion\.14\] line \d+ lus.b==0: SUCCESS$ +^\[main\.assertion\.15\] line \d+ lus2.a==3: SUCCESS$ +^\[main\.assertion\.16\] line \d+ lus2.b==4: SUCCESS$ +^\[main\.assertion\.17\] line \d+ lus3.a==3: SUCCESS$ +^\[main\.assertion\.18\] line \d+ lus3.b==4: SUCCESS$ +^\[main\.assertion\.19\] line \d+ lus4.a==3: SUCCESS$ +^\[main\.assertion\.20\] line \d+ lus4.b==0: SUCCESS$ +^\[main\.assertion\.21\] line \d+ lus5.a==0: SUCCESS$ +^\[main\.assertion\.22\] line \d+ lus5.b==4: SUCCESS$ +^\[main\.assertion\.23\] line \d+ lus6.a==3: SUCCESS$ +^\[main\.assertion\.24\] line \d+ lus6.b==4: SUCCESS$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc index 3dfcbcb927c..652444a902a 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-goto-after-function/test.desc @@ -3,7 +3,7 @@ main.c --function test_param_function --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ -\[test_param_function.assertion\.1\] line 15 a==5: SUCCESS -\[test_param_function.assertion\.2\] line 24 a==10: UNKNOWN -\[test_param_function.assertion\.3\] line 25 b==7: SUCCESS +\[test_param_function.assertion\.1\] line \d+ a==5: SUCCESS +\[test_param_function.assertion\.2\] line \d+ a==10: UNKNOWN +\[test_param_function.assertion\.3\] line \d+ b==7: SUCCESS -- diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc index 2414be0a86a..ba0b1531e42 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_3/test.desc @@ -3,6 +3,6 @@ main.c --function global_test --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[global_test\.assertion\.1\] line 67 global==42: SUCCESS$ -^\[global_test\.assertion\.2\] line 70 global==50: UNKNOWN$ +^\[global_test\.assertion\.1\] line \d+ global==42: SUCCESS$ +^\[global_test\.assertion\.2\] line \d+ global==50: UNKNOWN$ -- diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc index c9c02c43753..2312189b723 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-struct/test.desc @@ -3,12 +3,12 @@ main.c --function pass_param --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ -^\[pass_param\.assertion\.1\] line 25 human_instance.age==24: SUCCESS$ -^\[pass_param\.assertion\.2\] line 26 human_instance.height==1.80: SUCCESS$ -^\[pass_param\.assertion\.3\] line 29 human_instance.age==10: SUCCESS$ -^\[pass_param\.assertion\.4\] line 30 human_instance.age==24: FAILURE \(if reachable\)$ -^\[pass_param\.assertion\.5\] line 31 human_instance.height==1.80: SUCCESS$ -^\[pass_param\.assertion\.6\] line 34 human_instance.age==32: UNKNOWN$ -^\[pass_param\.assertion\.7\] line 35 human_instance.age==10: UNKNOWN$ -^\[pass_param\.assertion\.8\] line 36 human_instance.height==1.80: SUCCESS$ +^\[pass_param\.assertion\.1\] line \d+ human_instance.age==24: SUCCESS$ +^\[pass_param\.assertion\.2\] line \d+ human_instance.height==1.80: SUCCESS$ +^\[pass_param\.assertion\.3\] line \d+ human_instance.age==10: SUCCESS$ +^\[pass_param\.assertion\.4\] line \d+ human_instance.age==24: FAILURE \(if reachable\)$ +^\[pass_param\.assertion\.5\] line \d+ human_instance.height==1.80: SUCCESS$ +^\[pass_param\.assertion\.6\] line \d+ human_instance.age==32: UNKNOWN$ +^\[pass_param\.assertion\.7\] line \d+ human_instance.age==10: UNKNOWN$ +^\[pass_param\.assertion\.8\] line \d+ human_instance.height==1.80: SUCCESS$ -- diff --git a/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc b/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc index b08db01e7a7..fba07697856 100644 --- a/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-bit-field-constants/test.desc @@ -3,6 +3,6 @@ main.c --function main --variable-sensitivity --vsd-structs --verify ^EXIT=0$ ^SIGNAL=0$ -\[main\.assertion\.1\] line 12 bs\.byte==10: SUCCESS -\[main\.assertion\.2\] line 13 bs\.bitfield==1: SUCCESS +\[main\.assertion\.1\] line \d+ bs\.byte==10: SUCCESS +\[main\.assertion\.2\] line \d+ bs\.bitfield==1: SUCCESS -- diff --git a/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc b/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc index e23f825c23d..1598b5061e4 100644 --- a/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-bit-field-intervals/test.desc @@ -3,6 +3,6 @@ main.c --function main --variable-sensitivity --vsd-structs --vsd-intervals --verify ^EXIT=0$ ^SIGNAL=0$ -\[main\.assertion\.1\] line 12 bs\.byte==10: SUCCESS -\[main\.assertion\.2\] line 13 bs\.bitfield==1: SUCCESS +\[main\.assertion\.1\] line \d+ bs\.byte==10: SUCCESS +\[main\.assertion\.2\] line \d+ bs\.bitfield==1: SUCCESS -- diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc index d14f1aa42db..4106d2b61f4 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-merge/test.desc @@ -3,5 +3,5 @@ main.c --dependence-graph-vs --vsd-structs --vsd-arrays --verify ^EXIT=0$ ^SIGNAL=0$ -^\[main\.assertion\.1\] line 20 s_str.idx > 1: UNKNOWN$ +^\[main\.assertion\.1\] line \d+ s_str.idx > 1: UNKNOWN$ -- diff --git a/regression/goto-analyzer/write-stack-types/test.desc b/regression/goto-analyzer/write-stack-types/test.desc index d89557f46c6..647f6609d04 100644 --- a/regression/goto-analyzer/write-stack-types/test.desc +++ b/regression/goto-analyzer/write-stack-types/test.desc @@ -3,6 +3,6 @@ write-stack-address-of.c --variable-sensitivity --vsd-structs --vsd-pointers --verify ^EXIT=0$ ^SIGNAL=0$ -^\[func1\.assertion\.1\] line 15 func1.a == 0: UNKNOWN$ +^\[func1\.assertion\.1\] line \d+ func1.a == 0: UNKNOWN$ -- ^warning: ignoring From ccdd452d85f3a4d3c807f041efd722e7842a6eaa Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 18 Aug 2020 13:50:44 +0100 Subject: [PATCH 325/342] Create a new abstract interpreter that does a three-way merge Three-way merging is a VSD specific feature. On function call return, rather than just merging in the final state of the function to the return context, it computes the difference between the first and last states and then merges that into the calling state. The key difference is that if there are multiple calling contexts, their state will be merged and normally picked up. For example; global = 1; global = 2; f00(); f00(); The start of f00 must have global as the merge of the two (i.e. top if constant) and this will be merged into the return state -- even if f00 obviously does not touch global. Three-way merge only modifies the variables that change during f00 so in this case, global will be unmodified in both contexts. All of this only makes sense if there are multiple calling locations that merge into the same history. So if a fully context sensitive history is used then there is no point using three-way-merge. This commit also updates the tests that actually need this functionality. They demonstrate some of the other advantages of this technique. --- .../test.desc | 19 +- .../test.desc | 11 +- src/analyses/Makefile | 1 + .../three_way_merge_abstract_interpreter.cpp | 255 ++++++++++++++++++ .../three_way_merge_abstract_interpreter.h | 53 ++++ .../goto_analyzer_parse_options.cpp | 19 +- .../goto_analyzer_parse_options.h | 1 + 7 files changed, 343 insertions(+), 16 deletions(-) create mode 100644 src/analyses/variable-sensitivity/three_way_merge_abstract_interpreter.cpp create mode 100644 src/analyses/variable-sensitivity/three_way_merge_abstract_interpreter.h diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc index 959a2dd1562..8f66b407435 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple/test.desc @@ -1,14 +1,15 @@ CORE main.c ---function pointer_test --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify +--function pointer_test --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify --three-way-merge ^EXIT=0$ ^SIGNAL=0$ -^\[pointer_test.assertion\.1\] line 41 j==1: SUCCESS$ -^\[pointer_test.assertion\.2\] line 42 i==10: SUCCESS$ -^\[pointer_test.assertion\.3\] line 47 j==2: SUCCESS$ -^\[pointer_test.assertion\.4\] line 48 i==10: SUCCESS$ -^\[pointer_test.assertion\.5\] line 53 j==3: SUCCESS$ -^\[pointer_test.assertion\.6\] line 54 i==11: UNKNOWN$ -^\[pointer_test.assertion\.7\] line 59 j==4: SUCCESS$ -^\[pointer_test.assertion\.8\] line 60 i==11: UNKNOWN$ +^\[pointer_test.assertion\.1\] line \d+ j==1: SUCCESS$ +^\[pointer_test.assertion\.2\] line \d+ i==10: SUCCESS$ +^\[pointer_test.assertion\.3\] line \d+ j==2: SUCCESS$ +^\[pointer_test.assertion\.4\] line \d+ i==10: SUCCESS$ +^\[pointer_test.assertion\.5\] line \d+ j==3: SUCCESS$ +^\[pointer_test.assertion\.6\] line \d+ i==11: UNKNOWN$ +^\[pointer_test.assertion\.7\] line \d+ j==4: SUCCESS$ +^\[pointer_test.assertion\.8\] line \d+ i==11: UNKNOWN$ -- +j==2, j==3 and j==4 are the bits that specifically need three-way-merge diff --git a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc index 5f0d24e90bd..e9f61c5c785 100644 --- a/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-assign-aware-merge-simple_2/test.desc @@ -1,10 +1,11 @@ CORE main.c ---function simple_test --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify +--function simple_test --variable-sensitivity --vsd-pointers --vsd-arrays --vsd-structs --verify --three-way-merge ^EXIT=0$ ^SIGNAL=0$ -^\[simple_test\.assertion\.1\] line 25 i==0: SUCCESS$ -^\[simple_test\.assertion\.2\] line 26 global==0: SUCCESS$ -^\[simple_test\.assertion\.3\] line 31 i==1: SUCCESS$ -^\[simple_test\.assertion\.4\] line 32 global==2: SUCCESS$ +^\[simple_test\.assertion\.1\] line \d+ i==0: SUCCESS$ +^\[simple_test\.assertion\.2\] line \d+ global==0: SUCCESS$ +^\[simple_test\.assertion\.3\] line \d+ i==1: SUCCESS$ +^\[simple_test\.assertion\.4\] line \d+ global==2: SUCCESS$ -- +i==1 and global==2 specifically need three-way-merge \ No newline at end of file diff --git a/src/analyses/Makefile b/src/analyses/Makefile index ceef596a30a..27c490303d7 100644 --- a/src/analyses/Makefile +++ b/src/analyses/Makefile @@ -59,6 +59,7 @@ SRC = ai.cpp \ variable-sensitivity/value_set_abstract_value.cpp \ variable-sensitivity/value_set_pointer_abstract_object.cpp \ variable-sensitivity/value_set_array_abstract_object.cpp \ + variable-sensitivity/three_way_merge_abstract_interpreter.cpp \ # Empty last line INCLUDES= -I .. diff --git a/src/analyses/variable-sensitivity/three_way_merge_abstract_interpreter.cpp b/src/analyses/variable-sensitivity/three_way_merge_abstract_interpreter.cpp new file mode 100644 index 00000000000..d5aea6807a0 --- /dev/null +++ b/src/analyses/variable-sensitivity/three_way_merge_abstract_interpreter.cpp @@ -0,0 +1,255 @@ +/*******************************************************************\ + +Module: Variable sensitivity domain + +Author: Martin Brain, martin.brain@cs.ox.ac.uk + +Date: August 2020 + +\*******************************************************************/ + +/// \file +/// An abstract interpreter, based on the default recursive-interprocedural +/// that uses variable sensitivity domain's three-way-merge operation on +/// returning from a function call. This gives some of the precision of +/// context-sensitive analysis but at a fraction of the cost. The really +/// key thing is that it distinguishes between variables that are modified in +/// the function (or things called from it) and those that appear modified +/// because they have different values at different call sites. This is +/// especially important for preserving the value of (unmodified) global +/// variables. + +#include +#include + +bool ai_three_way_merget::visit_edge_function_call( + const irep_idt &calling_function_id, + trace_ptrt p_call, + locationt l_return, + const irep_idt &callee_function_id, + working_sett &working_set, + const goto_programt &callee, + const goto_functionst &goto_functions, + const namespacet &ns) +{ + // There are four locations that matter. + locationt l_call_site = p_call->current_location(); + locationt l_callee_start = callee.instructions.begin(); + locationt l_callee_end = --callee.instructions.end(); + locationt l_return_site = l_return; + + PRECONDITION(l_call_site->is_function_call()); + DATA_INVARIANT( + l_callee_end->is_end_function(), + "The last instruction of a goto_program must be END_FUNCTION"); + + // Histories for call_site and callee_start are easy + trace_ptrt p_call_site = p_call; + + auto next = p_call_site->step( + l_callee_start, + *(storage->abstract_traces_before(l_callee_start)), + ai_history_baset::no_caller_history); + if(next.first == ai_history_baset::step_statust::BLOCKED) + { + // Unexpected... + // We can't three-way merge without a callee start so + return false; + } + trace_ptrt p_callee_start = next.second; + + // Handle the function call recursively + { + working_sett catch_working_set; // The starting trace for the next fixpoint + + // Do the edge from the call site to the beginning of the function + // (This will compute p_callee_start but that is OK) + bool new_data = visit_edge( + calling_function_id, + p_call, + callee_function_id, + l_callee_start, + ai_history_baset:: + no_caller_history, // Not needed as p_call already has the info + ns, + catch_working_set); + + // do we need to do/re-do the fixedpoint of the body? + if(new_data) + fixedpoint( + get_next(catch_working_set), // Should be p_callee_start... + callee_function_id, + callee, + goto_functions, + ns); + } + + // Now we can give histories for the return part + + // Find the histories at the end of the function + auto traces = storage->abstract_traces_before(l_callee_end); + + bool new_data = false; // Whether we have changed a domain in the caller + + // As with recursive-interprocedural, there are potentially multiple histories + // at the end, or maybe none. Only some of these will be 'descendents' of + // p_call_site and p_callee_start + for(auto p_callee_end : *traces) + { + // First off, is it even reachable? + const statet &s_callee_end = get_state(p_callee_end); + + if(s_callee_end.is_bottom()) + continue; // Unreachable in callee -- no need to merge + + // Can it return to p_call_site? + auto return_step = p_callee_end->step( + l_return_site, + *(storage->abstract_traces_before(l_return_site)), + p_call_site); // Because it is a return edge! + if(return_step.first == ai_history_baset::step_statust::BLOCKED) + continue; // Can't return -- no need to merge + + // The fourth history! + trace_ptrt p_return_site = return_step.second; + + const std::unique_ptr ptr_s_callee_end_copy( + make_temporary_state(s_callee_end)); + auto tmp = + dynamic_cast(&(*ptr_s_callee_end_copy)); + INVARIANT(tmp != nullptr, "Three-way merge requires domain support"); + variable_sensitivity_domaint &s_working = *tmp; + + // Apply transformer + // This is for an end_function instruction which normally doesn't do much + // but in VSD it does, so this cannot be omitted. + s_working.transform( + callee_function_id, + l_callee_end, + calling_function_id, + l_return_site, + *this, + ns); + + // TODO : this is probably needed to avoid three_way_merge modifying one of + // it's arguments as it goes. A better solution would be to refactor + // merge_three_way_function_return. + const std::unique_ptr ptr_s_working_copy( + make_temporary_state(s_working)); + + s_working.merge_three_way_function_return( + get_state(p_call_site), + get_state(p_callee_start), + *ptr_s_working_copy, + ns); + + if( + merge(s_working, p_callee_end, p_return_site) || + (return_step.first == ai_history_baset::step_statust::NEW && + !s_working.is_bottom())) + { + put_in_working_set(working_set, p_return_site); + new_data = true; + } + } + + return new_data; +} + +#if 0 + // This is the edge from function end to return site. + + { + if(end_state.is_bottom()) + return false; // function exit point not reachable + + working_sett working_set; // Redundant; visit will add l_return + +- return visit_edge( +- f_it->first, l_end, calling_function_id, l_return, ns, working_set); ++ const std::unique_ptr tmp_state(make_temporary_state(end_state)); ++ tmp_state->transform(f_it->first, l_end, f_it->first, l_return, *this, ns); ++ ++ const std::unique_ptr pre_merge_state{ ++ make_temporary_state(*tmp_state)}; ++ ++ const locationt l_begin = goto_function.body.instructions.begin(); ++ tmp_state->merge_three_way_function_return( ++ get_state(l_call), get_state(l_begin), *pre_merge_state, ns); ++ ++ return merge(*tmp_state, l_end, l_return); + } + +#endif + +#if 0 +bool ai_baset::visit_edge( + const irep_idt &function_id, + trace_ptrt p, + const irep_idt &to_function_id, + locationt to_l, + trace_ptrt caller_history, + const namespacet &ns, + working_sett &working_set) +{ + // We only care about the return cases + if (caller_history == ai_history_baset::no_caller_history) { + return ai_recursive_interproceduralt::visit_edge(function_id, p, to_function_id, to_l, caller_history, ns, working_set); + } + + // There are four histories / locations / domains we care about + // In chronological order... + + trace_ptr call_site_history = caller_history; + statet &call_site_state = get_state(call_site_history); + locationt call_site_location = call_site_history.current_location(); + INVARIANT(call_site_location->is_function_call(), "caller_history implies that is is a function call"); + + trace_ptr callee_start_history = TBD; + statet &callee_start_state = get_state(callee_start_history); + locationt callee_start_location = callee_start_history.current_location(); + + trace_ptr callee_end_history = p; + statet &callee_end_state = get_state(callee_end_history); + locationt callee_end_location = callee_end_history.current_location(); + INVARIANT(callee_end_location->is_end_function(), "TBD"); + + trace_ptr return_site_history = STEP; + statet &return_site_state = get_state(return_site_history); + locationt return_site_location = to_l; + INVARIANT(std::next(call_site_location) == to_l, "TBD"); + + + + // Has history taught us not to step here... + auto next = + p->step(to_l, *(storage->abstract_traces_before(to_l)), caller_history); + if(next.first == ai_history_baset::step_statust::BLOCKED) + return false; + trace_ptrt to_p = next.second; + + // Abstract domains are mutable so we must copy before we transform + statet ¤t = get_state(p); + + std::unique_ptr tmp_state(make_temporary_state(current)); + statet &new_values = *tmp_state; + + // Apply transformer + new_values.transform(function_id, p, to_function_id, to_p, *this, ns); + + // Expanding a domain means that it has to be analysed again + // Likewise if the history insists that it is a new trace + // (assuming it is actually reachable). + if( + merge(new_values, p, to_p) || + (next.first == ai_history_baset::step_statust::NEW && + !new_values.is_bottom())) + { + put_in_working_set(working_set, to_p); + return true; + } + + return false; +} + +#endif diff --git a/src/analyses/variable-sensitivity/three_way_merge_abstract_interpreter.h b/src/analyses/variable-sensitivity/three_way_merge_abstract_interpreter.h new file mode 100644 index 00000000000..9e2d0a94ef2 --- /dev/null +++ b/src/analyses/variable-sensitivity/three_way_merge_abstract_interpreter.h @@ -0,0 +1,53 @@ +/*******************************************************************\ + +Module: Variable sensitivity domain + +Author: Martin Brain, martin.brain@cs.ox.ac.uk + +Date: August 2020 + +\*******************************************************************/ + +/// \file +/// An abstract interpreter, based on the default recursive-interprocedural +/// that uses variable sensitivity domain's three-way-merge operation on +/// returning from a function call. This gives some of the precision of +/// context-sensitive analysis but at a fraction of the cost. The really +/// key thing is that it distinguishes between variables that are modified in +/// the function (or things called from it) and those that appear modified +/// because they have different values at different call sites. This is +/// especially important for preserving the value of (unmodified) global +/// variables. + +#ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_THREE_WAY_MERGE_ABSTRACT_INTERPRETER_H +#define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_THREE_WAY_MERGE_ABSTRACT_INTERPRETER_H + +#include + +class ai_three_way_merget : public ai_recursive_interproceduralt +{ +public: + ai_three_way_merget( + std::unique_ptr &&hf, + std::unique_ptr &&df, + std::unique_ptr &&st) + : ai_recursive_interproceduralt(std::move(hf), std::move(df), std::move(st)) + { + } + +protected: + // Like ai_recursive_interproceduralt we hook the handling of function calls. + // Much of this is the same as ai_recursive_interproceduralt's handling but + // on function return the three-way merge is used. + bool visit_edge_function_call( + const irep_idt &calling_function_id, + trace_ptrt p_call, + locationt l_return, + const irep_idt &callee_function_id, + working_sett &working_set, + const goto_programt &callee, + const goto_functionst &goto_functions, + const namespacet &ns) override; +}; + +#endif diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp index 0573e86cd83..1b11efd2611 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.cpp +++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp @@ -51,6 +51,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include #include #include @@ -259,6 +260,8 @@ void goto_analyzer_parse_optionst::get_command_line_options(optionst &options) // Abstract interpreter choice if(cmdline.isset("recursive-interprocedural")) options.set_option("recursive-interprocedural", true); + else if(cmdline.isset("three-way-merge")) + options.set_option("three-way-merge", true); else if(cmdline.isset("legacy-ait") || cmdline.isset("location-sensitive")) { options.set_option("legacy-ait", true); @@ -444,7 +447,9 @@ ai_baset *goto_analyzer_parse_optionst::build_analyzer( const namespacet &ns) { // These support all of the option categories - if(options.get_bool_option("recursive-interprocedural")) + if( + options.get_bool_option("recursive-interprocedural") || + options.get_bool_option("three-way-merge")) { // Build the history factory std::unique_ptr hf = nullptr; @@ -507,7 +512,15 @@ ai_baset *goto_analyzer_parse_optionst::build_analyzer( return new ai_recursive_interproceduralt( std::move(hf), std::move(df), std::move(st)); } - UNREACHABLE; + else if(options.get_bool_option("three-way-merge")) + { + // Only works with VSD + if(options.get_bool_option("vsd")) + { + return new ai_three_way_merget( + std::move(hf), std::move(df), std::move(st)); + } + } } } else if(options.get_bool_option("legacy-ait")) @@ -941,6 +954,8 @@ void goto_analyzer_parse_optionst::help() // NOLINTNEXTLINE(whitespace/line_length) " --recursive-interprocedural use recursion to handle interprocedural reasoning\n" // NOLINTNEXTLINE(whitespace/line_length) + " --three-way-merge use VSD's three-way merge on return from function call\n" + // NOLINTNEXTLINE(whitespace/line_length) " --legacy-ait recursion for function and one domain per location\n" // NOLINTNEXTLINE(whitespace/line_length) " --legacy-concurrent legacy-ait with an extended fixed-point for concurrency\n" diff --git a/src/goto-analyzer/goto_analyzer_parse_options.h b/src/goto-analyzer/goto_analyzer_parse_options.h index 409fbf341a9..6a65438aa06 100644 --- a/src/goto-analyzer/goto_analyzer_parse_options.h +++ b/src/goto-analyzer/goto_analyzer_parse_options.h @@ -115,6 +115,7 @@ class optionst; #define GOTO_ANALYSER_OPTIONS_AI \ "(recursive-interprocedural)" \ + "(three-way-merge)" \ "(legacy-ait)" \ "(legacy-concurrent)" From f247dcb3163eeb075eec3d56ed673418ad7e552d Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 24 Aug 2020 21:01:11 +0100 Subject: [PATCH 326/342] Enable three-way merge for the tests that need it --- .../goto-analyzer/value-set-function-pointers-arrays/test.desc | 2 +- .../goto-analyzer/value-set-function-pointers-simple/test.desc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/regression/goto-analyzer/value-set-function-pointers-arrays/test.desc b/regression/goto-analyzer/value-set-function-pointers-arrays/test.desc index fbcfd4e0cf5..8f89cd771a0 100644 --- a/regression/goto-analyzer/value-set-function-pointers-arrays/test.desc +++ b/regression/goto-analyzer/value-set-function-pointers-arrays/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --vsd-value-sets --show --pointer-check +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --vsd-value-sets --show --pointer-check --three-way-merge ^file main.c line 29 function main: replacing function pointer by 2 possible targets$ ^file main.c line 40 function main: replacing function pointer by 2 possible targets$ ^main::1::fun1 \(\) -> value-set-begin: ptr ->\([fg]\), ptr ->\([fg]\), :value-set-end$ diff --git a/regression/goto-analyzer/value-set-function-pointers-simple/test.desc b/regression/goto-analyzer/value-set-function-pointers-simple/test.desc index 42cf759016d..6906c50e1a6 100644 --- a/regression/goto-analyzer/value-set-function-pointers-simple/test.desc +++ b/regression/goto-analyzer/value-set-function-pointers-simple/test.desc @@ -1,6 +1,6 @@ CORE main.c ---variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --vsd-value-sets --show --pointer-check +--variable-sensitivity --vsd-structs --vsd-arrays --vsd-pointers --vsd-value-sets --show --pointer-check --three-way-merge ^file main.c line 25 function main: replacing function pointer by 2 possible targets$ ^file main.c line 28 function main: replacing function pointer by 2 possible targets$ ^file main.c line 33 function main: replacing function pointer by 2 possible targets$ From dc7c4bd1dad58b5e503216d045ef65557e6c6b11 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 24 Aug 2020 21:03:17 +0100 Subject: [PATCH 327/342] Update line numbers for domains that track changes --- .../test.desc | 56 ++++++------- .../test.desc | 54 ++++++------- .../test.desc | 64 +++++++-------- .../test.desc | 78 +++++++++---------- .../test.desc | 6 +- 5 files changed, 129 insertions(+), 129 deletions(-) diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc index dbe314cf20f..8118d3636c0 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc @@ -8,31 +8,31 @@ activate-multi-line-match main#return_value \(\) -> TOP @ \[1\] __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] -__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[7\] -__CPROVER_malloc_object \(\) -> TOP @ \[8\] -__CPROVER_malloc_size \(\) -> 0ull? @ \[9\] -__CPROVER_memory_leak \(\) -> TOP @ \[10\] -__CPROVER_next_thread_id \(\) -> 0ul @ \[11\] -__CPROVER_pipe_count \(\) -> 0u @ \[13\] -__CPROVER_rounding_mode \(\) -> 0 @ \[14\] -__CPROVER_thread_id \(\) -> 0ul @ \[15\] -__CPROVER_threads_exited \(\) -> TOP @ \[18\] -do_arrays::1::bool_ \(\) -> TOP @ \[20\] -do_arrays::1::bool_1 \(\) -> TOP @ \[21\] -do_arrays::1::bool_2 \(\) -> TOP @ \[22\] -do_arrays::1::x \(\) -> \{\[0\] = 10 @ \[24\]\n\} @ \[24\] -do_arrays::1::x \(\) -> \{\[0\] = 10 @ \[24\]\n\[1\] = 20 @ \[25\]\n\} @ \[25\] -do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[26\]\n\[1\] = 20 @ \[25\]\n\} @ \[26\] -do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[26\]\n\[1\] = 40 @ \[27\]\n\} @ \[27\] -do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[26\]\n\[1\] = 30 @ \[28\]\n\} @ \[28\] -do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[29\]\n\[1\] = 30 @ \[28\]\n\} @ \[29\] -do_arrays::1::x \(\) -> \{\[0\] = 5 @ \[30\]\n\[1\] = 30 @ \[28\]\n\} @ \[30\] -do_arrays::1::x \(\) -> \{\[0\] = 15 @ \[31\]\n\[1\] = 30 @ \[28\]\n\} @ \[31\] -do_arrays::1::x \(\) -> \{\[0\] = 15 @ \[31\]\n\[1\] = 10 @ \[32\]\n\} @ \[32\] -do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[34\]\n\[1\] = 10 @ \[32\]\n\} @ \[34\] -do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[34\, 36\]\n\[1\] = 10 @ \[32\]\n\} @ \[34\, 36\] -do_arrays::1::x \(\) -> \{\[0\] = 0 @ \[38]\n\[1\] = 10 @ \[32\]\n\} @ \[38\] -do_arrays::1::x \(\) -> \{\[0\] = 3 @ \[40]\n\[1\] = 10 @ \[32\]\n\} @ \[40\] -do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[40\, 42]\n\[1\] = 10 @ \[32\]\n\} @ \[40\, 42\] -do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[40\, 42\, 45]\n\[1\] = 10 @ \[47\]\n\} @ \[47\] -do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[48]\n\[1\] = 10 @ \[47\]\n\} @ \[48\] +__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[10\] +__CPROVER_malloc_object \(\) -> TOP @ \[12\] +__CPROVER_malloc_size \(\) -> 0ull? @ \[13\] +__CPROVER_memory_leak \(\) -> TOP @ \[15\] +__CPROVER_next_thread_id \(\) -> 0ul @ \[16\] +__CPROVER_pipe_count \(\) -> 0u @ \[18\] +__CPROVER_rounding_mode \(\) -> 0 @ \[19\] +__CPROVER_thread_id \(\) -> 0ul @ \[20\] +__CPROVER_threads_exited \(\) -> TOP @ \[23\] +do_arrays::1::bool_ \(\) -> TOP @ \[25\] +do_arrays::1::bool_1 \(\) -> TOP @ \[26\] +do_arrays::1::bool_2 \(\) -> TOP @ \[27\] +do_arrays::1::x \(\) -> \{\[0\] = 10 @ \[29\]\n\} @ \[29\] +do_arrays::1::x \(\) -> \{\[0\] = 10 @ \[29\]\n\[1\] = 20 @ \[30\]\n\} @ \[30\] +do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[31\]\n\[1\] = 20 @ \[30\]\n\} @ \[31\] +do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[31\]\n\[1\] = 40 @ \[32\]\n\} @ \[32\] +do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[31\]\n\[1\] = 30 @ \[33\]\n\} @ \[33\] +do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[34\]\n\[1\] = 30 @ \[33\]\n\} @ \[34\] +do_arrays::1::x \(\) -> \{\[0\] = 5 @ \[35\]\n\[1\] = 30 @ \[33\]\n\} @ \[35\] +do_arrays::1::x \(\) -> \{\[0\] = 15 @ \[36\]\n\[1\] = 30 @ \[33\]\n\} @ \[36\] +do_arrays::1::x \(\) -> \{\[0\] = 15 @ \[36\]\n\[1\] = 10 @ \[37\]\n\} @ \[37\] +do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[39\]\n\[1\] = 10 @ \[37\]\n\} @ \[39\] +do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[39\, 41\]\n\[1\] = 10 @ \[37\]\n\} @ \[39\, 41\] +do_arrays::1::x \(\) -> \{\[0\] = 0 @ \[43]\n\[1\] = 10 @ \[37\]\n\} @ \[43\] +do_arrays::1::x \(\) -> \{\[0\] = 3 @ \[45]\n\[1\] = 10 @ \[37\]\n\} @ \[45\] +do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[45\, 47]\n\[1\] = 10 @ \[37\]\n\} @ \[45\, 47\] +do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[45\, 47\, 50]\n\[1\] = 10 @ \[52\]\n\} @ \[52\] +do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[53]\n\[1\] = 10 @ \[52\]\n\} @ \[53\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc index febd1e06be0..3fcd125d09b 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc @@ -8,30 +8,30 @@ activate-multi-line-match main#return_value \(\) -> TOP @ \[1\] __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] -__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[7\] -__CPROVER_malloc_object \(\) -> TOP @ \[8\] -__CPROVER_malloc_size \(\) -> 0ull? @ \[9\] -__CPROVER_memory_leak \(\) -> TOP @ \[10\] -__CPROVER_next_thread_id \(\) -> 0ul @ \[11\] -__CPROVER_pipe_count \(\) -> 0u @ \[13\] -__CPROVER_rounding_mode \(\) -> 0 @ \[14\] -__CPROVER_thread_id \(\) -> 0ul @ \[15\] -__CPROVER_threads_exited \(\) -> TOP @ \[18\] -do_pointers::1::bool_ \(\) -> TOP @ \[20\] -do_pointers::1::bool_1 \(\) -> TOP @ \[21\] -do_pointers::1::bool_2 \(\) -> TOP @ \[22\] -do_pointers::1::x \(\) -> TOP @ \[23\] -do_pointers::1::x \(\) -> 10 @ \[24\] -do_pointers::1::x_p \(\) -> TOP @ \[25\] -do_pointers::1::y \(\) -> TOP @ \[26\] -do_pointers::1::y \(\) -> 20 @ \[27\] -do_pointers::1::y_p \(\) -> TOP @ \[28\] -do_pointers::1::x_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[29\] -do_pointers::1::x \(\) -> 30 @ \[30\] -do_pointers::1::x \(\) -> 40 @ \[31\] -do_pointers::1::x \(\) -> TOP @ \[32\] -do_pointers::1::x \(\) -> 50 @ \[33\] -do_pointers::1::y_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[34\] -do_pointers::1::x \(\) -> 60 @ \[35\] -do_pointers::1::j \(\) -> TOP @ \[36\] -do_pointers::1::j \(\) -> 60 @ \[37\] +__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[10\] +__CPROVER_malloc_object \(\) -> TOP @ \[12\] +__CPROVER_malloc_size \(\) -> 0ull? @ \[13\] +__CPROVER_memory_leak \(\) -> TOP @ \[15\] +__CPROVER_next_thread_id \(\) -> 0ul @ \[16\] +__CPROVER_pipe_count \(\) -> 0u @ \[18\] +__CPROVER_rounding_mode \(\) -> 0 @ \[19\] +__CPROVER_thread_id \(\) -> 0ul @ \[20\] +__CPROVER_threads_exited \(\) -> TOP @ \[23\] +do_pointers::1::bool_ \(\) -> TOP @ \[25\] +do_pointers::1::bool_1 \(\) -> TOP @ \[26\] +do_pointers::1::bool_2 \(\) -> TOP @ \[27\] +do_pointers::1::x \(\) -> TOP @ \[28\] +do_pointers::1::x \(\) -> 10 @ \[29\] +do_pointers::1::x_p \(\) -> TOP @ \[30\] +do_pointers::1::y \(\) -> TOP @ \[31\] +do_pointers::1::y \(\) -> 20 @ \[32\] +do_pointers::1::y_p \(\) -> TOP @ \[33\] +do_pointers::1::x_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[34\] +do_pointers::1::x \(\) -> 30 @ \[35\] +do_pointers::1::x \(\) -> 40 @ \[36\] +do_pointers::1::x \(\) -> TOP @ \[37\] +do_pointers::1::x \(\) -> 50 @ \[38\] +do_pointers::1::y_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[39\] +do_pointers::1::x \(\) -> 60 @ \[40\] +do_pointers::1::j \(\) -> TOP @ \[41\] +do_pointers::1::j \(\) -> 60 @ \[42\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc index 9b8b89de92a..3b778cc9310 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc @@ -8,36 +8,36 @@ activate-multi-line-match main#return_value \(\) -> TOP @ \[1\] __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] -__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[7\] -__CPROVER_malloc_object \(\) -> TOP @ \[8\] -__CPROVER_malloc_size \(\) -> 0ull? @ \[9\] -__CPROVER_memory_leak \(\) -> TOP @ \[10\] -__CPROVER_next_thread_id \(\) -> 0ul @ \[11\] -__CPROVER_pipe_count \(\) -> 0u @ \[13\] -__CPROVER_rounding_mode \(\) -> 0 @ \[14\] -__CPROVER_thread_id \(\) -> 0ul @ \[15\] -__CPROVER_threads_exited \(\) -> TOP @ \[18\] -do_structs::1::bool_ \(\) -> TOP @ \[20\] -do_structs::1::bool_1 \(\) -> TOP @ \[21\] -do_structs::1::bool_2 \(\) -> TOP @ \[22\] -do_structs::1::st \(\) -> \{\} @ \[23\] -do_structs::1::st \(\) -> \{.x=10 @ \[24\]\} @ \[24\] -do_structs::1::st \(\) -> \{.x=10 @ \[24\]\, .y=20 @ \[25\]\} @ \[25\] -do_structs::1::st \(\) -> \{.x=30 @ \[26\]\, .y=20 @ \[25\]\} @ \[26\] -do_structs::1::st \(\) -> \{.x=30 @ \[26\]\, .y=40 @ \[27\]\} @ \[27\] -do_structs::1::st \(\) -> \{.x=30 @ \[26\]\, .y=30 @ \[28\]\} @ \[28\] -do_structs::1::st \(\) -> \{.x=30 @ \[29\]\, .y=30 @ \[28\]\} @ \[29\] -do_structs::1::st \(\) -> \{.x=5 @ \[30\]\, .y=30 @ \[28\]\} @ \[30\] -do_structs::1::st \(\) -> \{.x=15 @ \[31\]\, .y=30 @ \[28\]\} @ \[31\] -do_structs::1::st \(\) -> \{.x=15 @ \[31\]\, .y=10 @ \[32\]\} @ \[32\] -do_structs::1::st \(\) -> \{.x=20 @ \[34\]\, .y=10 @ \[32\]\} @ \[34\] -do_structs::1::st \(\) -> \{.x=20 @ \[34\, 36\]\, .y=10 @ \[32\]\} @ \[34\, 36\] -do_structs::1::st \(\) -> \{.x=0 @ \[38\]\, .y=10 @ \[32\]\} @ \[38\] -do_structs::1::st \(\) -> \{.x=3 @ \[40\]\, .y=10 @ \[32\]\} @ \[40\] -do_structs::1::st \(\) -> \{.x=TOP @ \[40\, 42\]\, .y=10 @ \[32\]\} @ \[40\, 42\] -do_structs::1::st \(\) -> \{.x=TOP @ \[40\, 42\, 45\]\, .y=10 @ \[32\]\} @ \[40\, 42\, 45\] -do_structs::1::st \(\) -> \{.x=TOP @ \[40\, 42\, 45\]\, .y=10 @ \[47\]\} @ \[47\] -do_structs::1::st \(\) -> \{.x=20 @ \[48\]\, .y=10 @ \[47\]\} @ \[48\] -do_structs::1::new_age \(\) -> \{\} @ \[49\] -do_structs::1::new_age \(\) -> \{.x=20 @ \[50\]\, .y=10 @ \[50\]\} @ \[50\] +__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[10\] +__CPROVER_malloc_object \(\) -> TOP @ \[12\] +__CPROVER_malloc_size \(\) -> 0ull? @ \[13\] +__CPROVER_memory_leak \(\) -> TOP @ \[15\] +__CPROVER_next_thread_id \(\) -> 0ul @ \[16\] +__CPROVER_pipe_count \(\) -> 0u @ \[18\] +__CPROVER_rounding_mode \(\) -> 0 @ \[19\] +__CPROVER_thread_id \(\) -> 0ul @ \[20\] +__CPROVER_threads_exited \(\) -> TOP @ \[23\] +do_structs::1::bool_ \(\) -> TOP @ \[25\] +do_structs::1::bool_1 \(\) -> TOP @ \[26\] +do_structs::1::bool_2 \(\) -> TOP @ \[27\] +do_structs::1::st \(\) -> \{\} @ \[28\] +do_structs::1::st \(\) -> \{.x=10 @ \[29\]\} @ \[29\] +do_structs::1::st \(\) -> \{.x=10 @ \[29\]\, .y=20 @ \[30\]\} @ \[30\] +do_structs::1::st \(\) -> \{.x=30 @ \[31\]\, .y=20 @ \[30\]\} @ \[31\] +do_structs::1::st \(\) -> \{.x=30 @ \[31\]\, .y=40 @ \[32\]\} @ \[32\] +do_structs::1::st \(\) -> \{.x=30 @ \[31\]\, .y=30 @ \[33\]\} @ \[33\] +do_structs::1::st \(\) -> \{.x=30 @ \[34\]\, .y=30 @ \[33\]\} @ \[34\] +do_structs::1::st \(\) -> \{.x=5 @ \[35\]\, .y=30 @ \[33\]\} @ \[35\] +do_structs::1::st \(\) -> \{.x=15 @ \[36\]\, .y=30 @ \[33\]\} @ \[36\] +do_structs::1::st \(\) -> \{.x=15 @ \[36\]\, .y=10 @ \[37\]\} @ \[37\] +do_structs::1::st \(\) -> \{.x=20 @ \[39\]\, .y=10 @ \[37\]\} @ \[39\] +do_structs::1::st \(\) -> \{.x=20 @ \[39\, 41\]\, .y=10 @ \[37\]\} @ \[39\, 41\] +do_structs::1::st \(\) -> \{.x=0 @ \[43\]\, .y=10 @ \[37\]\} @ \[43\] +do_structs::1::st \(\) -> \{.x=3 @ \[45\]\, .y=10 @ \[37\]\} @ \[45\] +do_structs::1::st \(\) -> \{.x=TOP @ \[45\, 47\]\, .y=10 @ \[37\]\} @ \[45\, 47\] +do_structs::1::st \(\) -> \{.x=TOP @ \[45\, 47\, 50\]\, .y=10 @ \[37\]\} @ \[45\, 47\, 50\] +do_structs::1::st \(\) -> \{.x=TOP @ \[45\, 47\, 50\]\, .y=10 @ \[52\]\} @ \[52\] +do_structs::1::st \(\) -> \{.x=20 @ \[53\]\, .y=10 @ \[52\]\} @ \[53\] +do_structs::1::new_age \(\) -> \{\} @ \[54\] +do_structs::1::new_age \(\) -> \{.x=20 @ \[55\]\, .y=10 @ \[55\]\} @ \[55\] -- diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc index f8ac0d87e84..7a8963718b2 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc @@ -7,43 +7,43 @@ main#return_value \(\) -> TOP @ \[1\] __CPROVER_alloca_object \(\) -> TOP @ \[4\] __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] -__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[7\] -__CPROVER_malloc_object \(\) -> TOP @ \[8\] -__CPROVER_malloc_size \(\) -> 0ull? @ \[9\] -__CPROVER_memory_leak \(\) -> TOP @ \[10\] -__CPROVER_next_thread_id \(\) -> 0ul @ \[11\] -__CPROVER_next_thread_key \(\) -> 0ul @ \[12\] -__CPROVER_pipe_count \(\) -> 0u @ \[13\] -__CPROVER_rounding_mode \(\) -> 0 @ \[14\] -__CPROVER_thread_id \(\) -> 0ul @ \[15\] -__CPROVER_thread_key_dtors \(\) -> TOP @ \[16\] -__CPROVER_thread_keys \(\) -> TOP @ \[17\] -__CPROVER_threads_exited \(\) -> TOP @ \[18\] -global_x \(\) -> 0 @ \[19\] -do_variables::1::bool_ \(\) -> TOP @ \[21\] -do_variables::1::bool_1 \(\) -> TOP @ \[22\] -do_variables::1::bool_2 \(\) -> TOP @ \[23\] -global_x \(\) -> 5 @ \[24\] -do_variables::1::x \(\) -> TOP @ \[25\] -do_variables::1::x \(\) -> 10 @ \[26\] -do_variables::1::y \(\) -> TOP @ \[27\] -do_variables::1::y \(\) -> 20 @ \[28\] -do_variables::1::x \(\) -> 30 @ \[29\] -do_variables::1::y \(\) -> 40 @ \[30\] -do_variables::1::y \(\) -> 30 @ \[31\] -do_variables::1::x \(\) -> 30 @ \[32\] -do_variables::1::x \(\) -> 5 @ \[33\] -do_variables::1::x \(\) -> 15 @ \[34\] -do_variables::1::y \(\) -> 10 @ \[35\] -do_variables::1::x \(\) -> 20 @ \[37\] -do_variables::1::x \(\) -> 20 @ \[37\, 39\] -do_variables::1::x \(\) -> 50 @ \[41\] -do_variables::1::x \(\) -> 20 @ \[43\] -do_variables::1::x \(\) -> TOP @ \[43\, 45\] -do_variables::1::x \(\) -> 0 @ \[47\] -do_variables::1::x \(\) -> 3 @ \[49\] -do_variables::1::x \(\) -> TOP @ \[49\, 51\] -do_variables::1::x \(\) -> TOP @ \[49\, 51\, 54\] -do_variables::1::y \(\) -> 10 @ \[56\] -do_variables::1::x \(\) -> 20 @ \[57\] +__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[10\] +__CPROVER_malloc_object \(\) -> TOP @ \[12\] +__CPROVER_malloc_size \(\) -> 0ull? @ \[13\] +__CPROVER_memory_leak \(\) -> TOP @ \[15\] +__CPROVER_next_thread_id \(\) -> 0ul @ \[16\] +__CPROVER_next_thread_key \(\) -> 0ul @ \[17\] +__CPROVER_pipe_count \(\) -> 0u @ \[18\] +__CPROVER_rounding_mode \(\) -> 0 @ \[19\] +__CPROVER_thread_id \(\) -> 0ul @ \[20\] +__CPROVER_thread_key_dtors \(\) -> TOP @ \[21\] +__CPROVER_thread_keys \(\) -> TOP @ \[22\] +__CPROVER_threads_exited \(\) -> TOP @ \[23\] +global_x \(\) -> 0 @ \[24\] +do_variables::1::bool_ \(\) -> TOP @ \[26\] +do_variables::1::bool_1 \(\) -> TOP @ \[27\] +do_variables::1::bool_2 \(\) -> TOP @ \[28\] +global_x \(\) -> 5 @ \[29\] +do_variables::1::x \(\) -> TOP @ \[30\] +do_variables::1::x \(\) -> 10 @ \[31\] +do_variables::1::y \(\) -> TOP @ \[32\] +do_variables::1::y \(\) -> 20 @ \[33\] +do_variables::1::x \(\) -> 30 @ \[34\] +do_variables::1::y \(\) -> 40 @ \[35\] +do_variables::1::y \(\) -> 30 @ \[36\] +do_variables::1::x \(\) -> 30 @ \[37\] +do_variables::1::x \(\) -> 5 @ \[38\] +do_variables::1::x \(\) -> 15 @ \[39\] +do_variables::1::y \(\) -> 10 @ \[40\] +do_variables::1::x \(\) -> 20 @ \[42\] +do_variables::1::x \(\) -> 20 @ \[42\, 44\] +do_variables::1::x \(\) -> 50 @ \[46\] +do_variables::1::x \(\) -> 20 @ \[48\] +do_variables::1::x \(\) -> TOP @ \[48\, 50\] +do_variables::1::x \(\) -> 0 @ \[52\] +do_variables::1::x \(\) -> 3 @ \[54\] +do_variables::1::x \(\) -> TOP @ \[54\, 56\] +do_variables::1::x \(\) -> TOP @ \[54\, 56\, 59\] +do_variables::1::y \(\) -> 10 @ \[61\] +do_variables::1::x \(\) -> 20 @ \[62\] -- diff --git a/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc b/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc index ba1d75f316a..9ea9f78f523 100644 --- a/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc +++ b/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc @@ -5,8 +5,8 @@ data-dependency-context.c activate-multi-line-match ^EXIT=0$ ^SIGNAL=0$ -st \(\) -> \{.a=.* @ \[2, 52\]\[Data dependencies: 52, 2\]\[Data dominators: \], .b=.* @ \[5, 52\]\[Data dependencies: 52, 5\]\[Data dominators: \]\} @ \[2, 5, 52\]\[Data dependencies: 52, 5, 2\]\[Data dominators: 52\] -ar \(\) -> \{\[0\] = TOP @ \[11\, 46\]\[Data dependencies: 46\, 11\]\[Data dominators: \]\n\[1\] = TOP @ \[14\, 46\]\[Data dependencies: 46\, 14\]\[Data dominators: \]\n\} @ \[11\, 14\, 46\]\[Data dependencies: 46\, 14\, 11\]\[Data dominators: 46\] -arr \(\) -> \{\[0\] = 1 @ \[19\]\[Data dependencies: 19\]\[Data dominators: 19\]\n\[1\] = 2 @ \[20\]\[Data dependencies: 20\]\[Data dominators: 20\]\n\[2\] = TOP @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: \]\n\} @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: 47\] +st \(\) -> \{.a=.* @ \[2, 57\]\[Data dependencies: 57, 2\]\[Data dominators: \], .b=.* @ \[5, 57\]\[Data dependencies: 57, 5\]\[Data dominators: \]\} @ \[2, 5, 57\]\[Data dependencies: 57, 5, 2\]\[Data dominators: 57\] +ar \(\) -> \{\[0\] = TOP @ \[11\, 51\]\[Data dependencies: 51\, 11\]\[Data dominators: \]\n\[1\] = TOP @ \[14\, 51\]\[Data dependencies: 51\, 14\]\[Data dominators: \]\n\} @ \[11\, 14\, 51\]\[Data dependencies: 51\, 14\, 11\]\[Data dominators: 51\] +arr \(\) -> \{\[0\] = 1 @ \[19\]\[Data dependencies: 19\]\[Data dominators: 19\]\n\[1\] = 2 @ \[20\]\[Data dependencies: 20\]\[Data dominators: 20\]\n\[2\] = TOP @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: \]\n\} @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: 52\] -- ^warning: ignoring From 74bc496e9a2d90dbfc2f8bb10e081f9ff82ac0c0 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 24 Aug 2020 21:11:16 +0100 Subject: [PATCH 328/342] Use three-way merge in the VSD dependency graph This requires a few legacy contortions similar to the ones done in dependency graph. --- .../variable_sensitivity_dependence_graph.cpp | 6 +++-- .../variable_sensitivity_dependence_graph.h | 24 ++++++++++++++----- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index 24e8e5b3e63..55e13dc04ce 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -632,8 +632,10 @@ class variable_sensitivity_dependence_domain_factoryt variable_sensitivity_dependence_grapht::variable_sensitivity_dependence_grapht( const goto_functionst &goto_functions, const namespacet &_ns) - : ait( - util_make_unique(*this)), + : ai_three_way_merget( + util_make_unique>(), + util_make_unique(*this), + util_make_unique()), goto_functions(goto_functions), ns(_ns) { diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h index fb94c0852b1..4530cd5f49b 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -8,6 +8,7 @@ #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DEPENDENCE_GRAPH_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DEPENDENCE_GRAPH_H +#include "three_way_merge_abstract_interpreter.h" #include "variable_sensitivity_domain.h" #include @@ -204,12 +205,24 @@ class variable_sensitivity_dependence_domaint class variable_sensitivity_dependence_domain_factoryt; -class variable_sensitivity_dependence_grapht - : public ait, - public grapht +class variable_sensitivity_dependence_grapht : public ai_three_way_merget, + public grapht { +protected: + // Legacy-style mutable access to the storage + virtual statet &get_state(locationt l) + { + auto &s = dynamic_cast(*storage); + return s.get_state(l, *domain_factory); + } + + variable_sensitivity_dependence_domaint &operator[](locationt l) + { + return dynamic_cast( + get_state(l)); + } + public: - using ait::operator[]; using grapht::operator[]; friend class variable_sensitivity_dependence_domaint; @@ -223,8 +236,7 @@ class variable_sensitivity_dependence_grapht void initialize(const irep_idt &function_id, const goto_programt &goto_program) { - ait::initialize( - function_id, goto_program); + ai_recursive_interproceduralt::initialize(function_id, goto_program); } void finalize() From 57e7d0119088dfccc1517d87b6df13a5cc0b950b Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 24 Aug 2020 21:13:00 +0100 Subject: [PATCH 329/342] Update the VSD dependency graph tests for line number changes These are due to new global variables being added to __CPROVER_initialise --- .../test.desc | 52 +++++++++---------- .../test.desc | 52 +++++++++---------- .../test.desc | 2 +- 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc index cd7f36370fb..0268705cfbe 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc @@ -3,35 +3,35 @@ main.c file1.c file2.c --dependence-graph-vs --vsd-structs --vsd-arrays --show ^EXIT=0$ ^SIGNAL=0$ -Data dependencies: 58 \[st.a\] -Data dependencies: 58 \[st.b\] -Data dependencies: 1 \[st.a\], 58 \[st.a\] -Data dependencies: 4 \[st.b\], 58 \[st.b\] -Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\] -Data dependencies: 52 \[ar\[\([^)]*\)0\]\] -Data dependencies: 52 \[ar\[\([^)]*\)1\]\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\] -Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\] +Data dependencies: 63 \[st.a\] +Data dependencies: 63 \[st.b\] +Data dependencies: 1 \[st.a\], 63 \[st.a\] +Data dependencies: 4 \[st.b\], 63 \[st.b\] +Data dependencies: 1 \[st.a\], 4 \[st.b\], 63 \[st.a, st.b\] +Data dependencies: 57 \[ar\[\([^)]*\)0\]\] +Data dependencies: 57 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\] +Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\] Data dependencies: 19 \[arr\[\([^)]*\)1\]\] Data dependencies: 18 \[arr\[\([^)]*\)0\]\] Data dependencies: 19 \[arr\[\([^)]*\)1\]\] Data dependencies: 20 \[arr\[\([^)]*\)2\]\], 22 \[arr\[\([^)]*\)2\]\] -Data dependencies: 1 \[st.a\], 58 \[st.a\], 62 \[st.a\] -Data dependencies: 4 \[st.b\], 58 \[st.b\], 65 \[st.b\] -Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\], 62 \[st.a\], 65 \[st.b\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\], 73 \[ar\[\([^)]*\)0\]\] -Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\], 76 \[ar\[\([^)]*\)1\]\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 73 \[ar\[\([^)]*\)0\]\], 76 \[ar\[\([^)]*\)1\]\] -Data dependencies: 1 \[st.a\], 58 \[st.a\] -Data dependencies: 4 \[st.b\], 58 \[st.b\] -Data dependencies: 1 \[st.a\], 58 \[st.a\], 62 \[st.a\] -Data dependencies: 4 \[st.b\], 58 \[st.b\], 65 \[st.b\] -Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\], 62 \[st.a\], 65 \[st.b\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\] -Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\], 73 \[ar\[\([^)]*\)0\]\] -Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\], 76 \[ar\[\([^)]*\)1\]\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 73 \[ar\[\([^)]*\)0\]\], 76 \[ar\[\([^)]*\)1\]\] +Data dependencies: 1 \[st.a\], 63 \[st.a\], 67 \[st.a\] +Data dependencies: 4 \[st.b\], 63 \[st.b\], 70 \[st.b\] +Data dependencies: 1 \[st.a\], 4 \[st.b\], 63 \[st.a, st.b\], 67 \[st.a\], 70 \[st.b\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\], 78 \[ar\[\([^)]*\)0\]\] +Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\], 81 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 78 \[ar\[\([^)]*\)0\]\], 81 \[ar\[\([^)]*\)1\]\] +Data dependencies: 1 \[st.a\], 63 \[st.a\] +Data dependencies: 4 \[st.b\], 63 \[st.b\] +Data dependencies: 1 \[st.a\], 63 \[st.a\], 67 \[st.a\] +Data dependencies: 4 \[st.b\], 63 \[st.b\], 70 \[st.b\] +Data dependencies: 1 \[st.a\], 4 \[st.b\], 63 \[st.a, st.b\], 67 \[st.a\], 70 \[st.b\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\] +Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\], 78 \[ar\[\([^)]*\)0\]\] +Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\], 81 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 78 \[ar\[\([^)]*\)0\]\], 81 \[ar\[\([^)]*\)1\]\] -- ^warning: ignoring diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc index 7970f84b12f..ff7855759f1 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc @@ -3,36 +3,36 @@ main.c file1.c file2.c --dependence-graph-vs --vsd-structs --vsd-arrays --show ^EXIT=0$ ^SIGNAL=0$ -^Data dependencies: 58 \[st.a\]$ -^Data dependencies: 58 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 58 \[st.a\]$ -^Data dependencies: 4 \[st.b\], 58 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\]$ -^Data dependencies: 52 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 63 \[st.a\]$ +^Data dependencies: 63 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 63 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 63 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 4 \[st.b\], 63 \[st.a, st.b\]$ +^Data dependencies: 57 \[ar\[\([^)]*\)0\]\]$ ^Data dependencies: 6 \[out1\]$ -^Data dependencies: 52 \[ar\[\([^)]*\)1\]\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\]$ -^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\]$ +^Data dependencies: 57 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\]$ ^Data dependencies: 19 \[arr\[\([^)]*\)1\]\]$ ^Data dependencies: 18 \[arr\[\([^)]*\)0\]\]$ ^Data dependencies: 19 \[arr\[\([^)]*\)1\]\]$ ^Data dependencies: 20 \[arr\[\([^)]*\)2\]\], 22 \[arr\[\([^)]*\)2\]\]$ -^Data dependencies: 1 \[st.a\], 58 \[st.a\], 62 \[st.a\]$ -^Data dependencies: 4 \[st.b\], 58 \[st.b\], 65 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\], 62 \[st.a\], 65 \[st.b\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\], 73 \[ar\[\([^)]*\)0\]\]$ -^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\], 76 \[ar\[\([^)]*\)1\]\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 73 \[ar\[\([^)]*\)0\]\], 76 \[ar\[\([^)]*\)1\]\]$ -^Data dependencies: 1 \[st.a\], 58 \[st.a\]$ -^Data dependencies: 4 \[st.b\], 58 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 58 \[st.a\], 62 \[st.a\]$ -^Data dependencies: 4 \[st.b\], 58 \[st.b\], 65 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 4 \[st.b\], 58 \[st.a, st.b\], 62 \[st.a\], 65 \[st.b\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\]$ -^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 52 \[ar\[\([^)]*\)0\]\], 73 \[ar\[\([^)]*\)0\]\]$ -^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)1\]\], 76 \[ar\[\([^)]*\)1\]\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 52 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 73 \[ar\[\([^)]*\)0\]\], 76 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 1 \[st.a\], 63 \[st.a\], 67 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 63 \[st.b\], 70 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 4 \[st.b\], 63 \[st.a, st.b\], 67 \[st.a\], 70 \[st.b\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\], 78 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\], 81 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 78 \[ar\[\([^)]*\)0\]\], 81 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 1 \[st.a\], 63 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 63 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 63 \[st.a\], 67 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 63 \[st.b\], 70 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 4 \[st.b\], 63 \[st.a, st.b\], 67 \[st.a\], 70 \[st.b\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\], 78 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\], 81 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 78 \[ar\[\([^)]*\)0\]\], 81 \[ar\[\([^)]*\)1\]\]$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc index da2322955fc..d8564343ea4 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc @@ -4,5 +4,5 @@ main.c activate-multi-line-match ^EXIT=0$ ^SIGNAL=0$ -\*\*\*\* 9 file .*main\.c line 22 function main\nControl dependencies: 34 \[UNCONDITIONAL\]\nData dependencies: 1 \[g_a\[\([^)]*\)i\]\], 2 \[g_a\[\([^)]*\)i\]\], 3 \[g_a\[\([^)]*\)i\]\], 7 \[g_a\[\([^)]*\)i\]\] +\*\*\*\* 9 file .*main\.c line 22 function main\nControl dependencies: 39 \[UNCONDITIONAL\]\nData dependencies: 1 \[g_a\[\([^)]*\)i\]\], 2 \[g_a\[\([^)]*\)i\]\], 3 \[g_a\[\([^)]*\)i\]\], 7 \[g_a\[\([^)]*\)i\]\] -- From 516567f43fba3173a3b8178b8162a5cd6591152e Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 25 Aug 2020 19:17:38 +0100 Subject: [PATCH 330/342] Update unit tests for the improved, type safe(r) exprts --- .../constant_array_abstract_object/merge.cpp | 44 ++++++++++--------- .../full_struct_abstract_object/merge.cpp | 18 ++++---- 2 files changed, 33 insertions(+), 29 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 6b62977272f..86b6597239b 100644 --- a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp @@ -80,16 +80,18 @@ SCENARIO( integer_typet(), from_integer(3, integer_typet())); // int val1[3] = {1, 2, 3} - exprt val1 = array_exprt(array_type); - val1.operands().push_back(from_integer(1, integer_typet())); - val1.operands().push_back(from_integer(2, integer_typet())); - val1.operands().push_back(from_integer(3, integer_typet())); + exprt::operandst val1_op; + val1_op.push_back(from_integer(1, integer_typet())); + val1_op.push_back(from_integer(2, integer_typet())); + val1_op.push_back(from_integer(3, integer_typet())); + exprt val1 = array_exprt(val1_op, array_type); // int val2[3] = {1, 4, 5} - exprt val2 = array_exprt(array_type); - val2.operands().push_back(from_integer(1, integer_typet())); - val2.operands().push_back(from_integer(4, integer_typet())); - val2.operands().push_back(from_integer(5, integer_typet())); + exprt::operandst val2_op; + val2_op.push_back(from_integer(1, integer_typet())); + val2_op.push_back(from_integer(4, integer_typet())); + val2_op.push_back(from_integer(5, integer_typet())); + exprt val2 = array_exprt(val2_op, array_type); // index_exprt for reading from an array const index_exprt i0 = @@ -131,9 +133,9 @@ SCENARIO( 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()); + REQUIRE(util.read_index(cast_result, i0) == val1.operands()[0]); + REQUIRE(util.read_index(cast_result, i1) == val1.operands()[1]); + REQUIRE(util.read_index(cast_result, i2) == val1.operands()[2]); // Is optimal REQUIRE(result == op1); @@ -161,7 +163,7 @@ SCENARIO( 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, i0) == val1.operands()[0]); REQUIRE(util.read_index(cast_result, i1) == nil_exprt()); REQUIRE(util.read_index(cast_result, i2) == nil_exprt()); @@ -219,9 +221,9 @@ SCENARIO( 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()); + REQUIRE(util.read_index(cast_result, i0) == val1.operands()[0]); + REQUIRE(util.read_index(cast_result, i1) == val1.operands()[1]); + REQUIRE(util.read_index(cast_result, i2) == val1.operands()[2]); // Is optimal REQUIRE(result == op1); @@ -335,9 +337,9 @@ SCENARIO( 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()); + REQUIRE(util.read_index(cast_result, i0) == val1.operands()[0]); + REQUIRE(util.read_index(cast_result, i1) == val1.operands()[1]); + REQUIRE(util.read_index(cast_result, i2) == val1.operands()[2]); // Is optimal REQUIRE(result != op1); @@ -452,9 +454,9 @@ SCENARIO( 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()); + REQUIRE(util.read_index(cast_result, i0) == val1.operands()[0]); + REQUIRE(util.read_index(cast_result, i1) == val1.operands()[1]); + REQUIRE(util.read_index(cast_result, i2) == val1.operands()[2]); // Is optimal 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 2d616f2bcd7..ed0a701a05c 100644 --- a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp @@ -110,16 +110,18 @@ SCENARIO( struct_type.components().push_back(comp_b); struct_type.components().push_back(comp_c); - struct_exprt val1(struct_type); - val1.operands().push_back(from_integer(1, integer_typet())); - val1.operands().push_back(from_integer(2, integer_typet())); - val1.operands().push_back(from_integer(3, integer_typet())); + exprt::operandst val1_op; + val1_op.push_back(from_integer(1, integer_typet())); + val1_op.push_back(from_integer(2, integer_typet())); + val1_op.push_back(from_integer(3, integer_typet())); + struct_exprt val1(val1_op, struct_type); // struct val1 = {.a = 1, .b = 4, .c = 5} - struct_exprt val2(struct_type); - val2.operands().push_back(from_integer(1, integer_typet())); - val2.operands().push_back(from_integer(4, integer_typet())); - val2.operands().push_back(from_integer(5, integer_typet())); + exprt::operandst val2_op; + val2_op.push_back(from_integer(1, integer_typet())); + val2_op.push_back(from_integer(4, integer_typet())); + val2_op.push_back(from_integer(5, integer_typet())); + struct_exprt val2(val2_op, struct_type); // index_exprt for reading from an array const member_exprt a(nil_exprt(), "a", integer_typet()); From 332237827c9708b9b6527cb8572cf2194a2d9a1e Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 25 Aug 2020 20:37:06 +0100 Subject: [PATCH 331/342] Tweak the VSDG to fix a clang specific warning about get_state --- .../variable_sensitivity_dependence_graph.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h index 4530cd5f49b..cf9f2a048ad 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -209,6 +209,8 @@ class variable_sensitivity_dependence_grapht : public ai_three_way_merget, public grapht { protected: + using ai_baset::get_state; + // Legacy-style mutable access to the storage virtual statet &get_state(locationt l) { From 69d5367bf78a293aa74ee52f21c2571572f19cdd Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 25 Aug 2020 23:32:11 +0100 Subject: [PATCH 332/342] One of the new unit tests was omitted from the source list The N_CATCH_TESTS check in the Makefile found this! --- unit/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/unit/Makefile b/unit/Makefile index c4aa28ca58d..905b2a47bce 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -17,6 +17,7 @@ SRC += analyses/ai/ai.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/eval.cpp \ analyses/variable-sensitivity/interval_abstract_value/meet.cpp \ analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp \ analyses/variable-sensitivity/last_written_location.cpp \ From c8a3315393292f7f605d3640f72b8c956a050337 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 25 Aug 2020 23:34:52 +0100 Subject: [PATCH 333/342] Update unit test for the bug fix to abstract_environmentt In a previous commit I fixed a bug where the default state of a constructed abstract_environment was top rather than bottom. Correcting this meant this unit test fails as the environment will only return objects which are bottom. Also improve the tagging of the test. --- unit/analyses/variable-sensitivity/eval.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/unit/analyses/variable-sensitivity/eval.cpp b/unit/analyses/variable-sensitivity/eval.cpp index 91c2cdd7d89..36eb2a369bf 100644 --- a/unit/analyses/variable-sensitivity/eval.cpp +++ b/unit/analyses/variable-sensitivity/eval.cpp @@ -15,13 +15,16 @@ static symbolt simple_symbol(const irep_idt &identifier, const typet &type) return b1; } -SCENARIO("eval", "[core]") +SCENARIO( + "eval", + "[core][analyses][variable-sensitivity][interval_abstract_value]") { GIVEN("An environment with intervals domain") { variable_sensitivity_object_factoryt::instance().set_options( vsd_configt::intervals()); abstract_environmentt environment; + environment.make_top(); // Domains are bottom on construction symbol_tablet symbol_table; namespacet ns{symbol_table}; From 593eec767ad3ec78e3d38b85df7eb00705b872c8 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 25 Aug 2020 23:36:49 +0100 Subject: [PATCH 334/342] Correct a typo in the creation of an interval Thankfully the names of the variables and the description of the tests makes it clear that this was a typo. Documentation FTW! --- .../variable-sensitivity/interval_abstract_value/meet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp b/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp index 6f69dd5dce6..3e7b4088a8c 100644 --- a/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp +++ b/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp @@ -28,7 +28,7 @@ SCENARIO( const auto varx = symbol_exprt(type); const auto x_le_10 = binary_relation_exprt(varx, ID_le, val10); - const auto lt_10_x = binary_relation_exprt(val10, ID_le, varx); + const auto lt_10_x = binary_relation_exprt(val10, ID_lt, varx); const exprt val2 = from_integer(2, type); const exprt val15 = from_integer(15, type); From 89177638fd4161766f4844163fede700e2b70c95 Mon Sep 17 00:00:00 2001 From: martin Date: Wed, 26 Aug 2020 21:28:20 +0100 Subject: [PATCH 335/342] Remove reference to non-public issue tracker --- .../simplify-lhs-pointer-array-dereference/main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/main.c b/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/main.c index 419434e47eb..7ba0d604c7e 100644 --- a/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/main.c +++ b/regression/goto-analyzer-simplify/simplify-lhs-pointer-array-dereference/main.c @@ -12,7 +12,6 @@ void main() // TODO: Currently writing to an offset pointer sets the domain to top // so recreate the variables to reign the domain back in - // This will be addressed by diffblue/cbmc-toyota#118 int new_array[] = {1, 2, 3, 4, 5}; int *new_pointer = new_array; From 46082206f750675dbce915abb1ec95f983710313 Mon Sep 17 00:00:00 2001 From: martin Date: Thu, 27 Aug 2020 18:50:29 +0100 Subject: [PATCH 336/342] Convert comments to the new(er) doxygen format --- .../abstract_enviroment.cpp | 430 +++++++----------- .../abstract_enviroment.h | 16 +- .../variable-sensitivity/abstract_object.cpp | 264 ++++------- .../variable-sensitivity/abstract_object.h | 77 ++-- .../abstract_object_statistics.h | 3 + .../variable-sensitivity/abstract_value.cpp | 63 +-- .../variable-sensitivity/abstract_value.h | 4 + .../array_abstract_object.cpp | 122 ++--- .../array_abstract_object.h | 4 + .../constant_abstract_value.cpp | 47 +- .../constant_abstract_value.h | 4 + .../constant_array_abstract_object.cpp | 266 ++++------- .../constant_array_abstract_object.h | 4 + .../constant_pointer_abstract_object.cpp | 247 ++++------ .../constant_pointer_abstract_object.h | 3 + .../context_abstract_object.h | 1 + .../full_struct_abstract_object.cpp | 223 ++++----- .../full_struct_abstract_object.h | 2 + .../interval_abstract_value.h | 4 + .../interval_array_abstract_object.h | 2 + .../pointer_abstract_object.cpp | 122 ++--- .../pointer_abstract_object.h | 2 + .../struct_abstract_object.cpp | 120 ++--- .../struct_abstract_object.h | 3 + .../union_abstract_object.cpp | 122 ++--- .../union_abstract_object.h | 3 + .../variable_sensitivity_dependence_graph.h | 4 + .../variable_sensitivity_domain.cpp | 225 ++++----- .../variable_sensitivity_domain.h | 113 ++--- .../variable_sensitivity_object_factory.cpp | 72 ++- .../variable_sensitivity_object_factory.h | 39 +- 31 files changed, 978 insertions(+), 1633 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index f8239c56b32..1243171860b 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -27,20 +27,13 @@ # include #endif -/*******************************************************************\ - -Function: abstract_environmentt::eval - - Inputs: - expr - the expression to evaluate - ns - the current namespace - - Outputs: The abstract_object representing the value of the expression - - Purpose: Evaluate the value of an expression relative to the current domain - -\*******************************************************************/ - +/// Function: abstract_environmentt::eval +/// Evaluate the value of an expression relative to the current domain +/// +/// \param expr: the expression to evaluate +/// \param ns: the current namespace +/// +/// \return The abstract_object representing the value of the expression abstract_object_pointert abstract_environmentt::eval(const exprt &expr, const namespacet &ns) const { @@ -128,40 +121,35 @@ abstract_environmentt::eval(const exprt &expr, const namespacet &ns) const } } -/*******************************************************************\ - -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. - - 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. -\*******************************************************************/ - +/// Function: abstract_environmentt::assign +/// +/// \param expr: the expression to assign to +/// \param value: the value to assign to the expression +/// \param ns: the namespace +/// +/// \return A boolean, true if the assignment has changed the domain. +/// +/// 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( const exprt &expr, const abstract_object_pointert value, @@ -269,31 +257,25 @@ bool abstract_environmentt::assign( return true; } -/*******************************************************************\ - -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 - ns - the namespace - merge_write - Are we 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 - -\*******************************************************************/ - +/// Function: abstract_object_pointert abstract_environmentt::write +/// +/// \param lhs: the abstract object for the left hand side of the write (i.e. the one +/// to update). +/// \param rhs: the value we are trying to write to the left hand side +/// \param remaining_stack: what is left of the stack before the rhs can replace or be +/// merged with the rhs +/// \param ns: the namespace +/// \param merge_write: Are we 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. +/// +/// \return A modified version of the rhs after the write has taken place +/// +/// 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, @@ -335,22 +317,20 @@ abstract_object_pointert abstract_environmentt::write( } } -/*******************************************************************\ - -Function: abstract_environmentt::assume - - Inputs: - expr - the expression that is to be assumed - ns - the current namespace - - Outputs: True if the assume changed the domain. - - Purpose: Reduces the domain to (an over-approximation) of the cases - when the the expression holds. Used to implement assume - statements and conditional branches. - -\*******************************************************************/ - +/// Function: abstract_environmentt::assume +/// +/// \param expr: the expression that is to be assumed +/// \param ns: the current namespace +/// +/// \return True if the assume changed the domain. +/// +/// Reduces the domain to (an over-approximation) of the cases +/// when the the expression holds. Used to implement assume +/// statements and conditional branches. +/// It would be valid to simply return false here because it +/// is an over-approximation. We try to do better than that. +/// The better the implementation the more precise the results +/// will be. bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) { // We should only attempt to assume Boolean things @@ -380,7 +360,7 @@ bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) /* TODO : full implementation here * Note that this is *very* syntax dependent so some normalisation would help - * 1. split up conjucts, handle each part separately + * 1. split up conjuncts, 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 @@ -399,22 +379,16 @@ bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) return false; } -/*******************************************************************\ - -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 - - Purpose: Look at the configuration for the sensitivity and create an - appropriate abstract_object - -\*******************************************************************/ - +/// Function: abstract_environmentt::abstract_object_factory +/// +/// \param type: the type of the object whose state should be tracked +/// \param top: does the type of the object start as top +/// \param bottom: does the type of the object start as bottom in the two-value domain +/// +/// \return The abstract object that has been created +/// +/// Look at the configuration for the sensitivity and create an +/// appropriate abstract_object abstract_object_pointert abstract_environmentt::abstract_object_factory( const typet &type, const namespacet &ns, @@ -426,21 +400,15 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( type, top, bottom, empty_constant_expr, *this, ns); } -/*******************************************************************\ - -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 - -\*******************************************************************/ - +/// Function: abstract_environmentt::abstract_object_factory +/// +/// \param type: the type of the object whose state should be tracked +/// \param expr: the starting value of the symbol +/// +/// \return The abstract object that has been created +/// +/// Look at the configuration for the sensitivity and create an +/// appropriate abstract_object, assigning an appropriate value abstract_object_pointert abstract_environmentt::abstract_object_factory( const typet &type, const exprt &e, @@ -449,23 +417,17 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( return abstract_object_factory(type, false, false, e, *this, 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 - -\*******************************************************************/ - +/// Function: abstract_environmentt::abstract_object_factory +/// +/// \param type: the type of the object whose state should be tracked +/// \param top: does the type of the object start as top in the two-value domain +/// \param bottom: does the type of the object start as bottom in the two-value domain +/// \param expr: the starting value of the symbol if top and bottom are both false +/// +/// \return The abstract object that has been created +/// +/// 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, @@ -478,19 +440,13 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( type, top, bottom, e, environment, ns); } -/*******************************************************************\ - -Function: abstract_environmentt::merge - - Inputs: - env - the other environment - - Outputs: A Boolean, true when the merge has changed something - - Purpose: Computes the join between "this" and "b" - -\*******************************************************************/ - +/// Function: abstract_environmentt::merge +/// +/// \param env: the other environment +/// +/// \return A Boolean, true when the merge has changed something +/// +/// Computes the join between "this" and "b" bool abstract_environmentt::merge(const abstract_environmentt &env) { // Use the sharing_map's "iterative over all differences" functionality @@ -529,37 +485,22 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) } } -/*******************************************************************\ - -Function: abstract_environmentt::havoc - - Inputs: - havoc_string - diagnostic string to track down havoc causing. - - Outputs: None - - Purpose: Set the domain to top - -\*******************************************************************/ - +/// Function: abstract_environmentt::havoc +/// +/// \param havoc_string: diagnostic string to track down havoc causing. +/// +/// \return None +/// +/// 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: None - - Outputs: None - - Purpose: Set the domain to top - -\*******************************************************************/ - +/// Function: abstract_environmentt::make_top +/// +/// Set the domain to top void abstract_environmentt::make_top() { // since we assume anything is not in the map is top this is sufficient @@ -567,73 +508,38 @@ void abstract_environmentt::make_top() bottom = false; } -/*******************************************************************\ - -Function: abstract_environmentt::make_bottom - - Inputs: None - - Outputs: None - - Purpose: Set the domain to top - -\*******************************************************************/ - +/// Function: abstract_environmentt::make_bottom +/// +/// Set the domain to top void abstract_environmentt::make_bottom() { map.clear(); bottom = true; } -/*******************************************************************\ - -Function: abstract_environmentt::is_bottom - - Inputs: - - Outputs: - - Purpose: Gets whether the domain is bottom - -\*******************************************************************/ - +/// abstract_environmentt::is_bottom +/// +/// Gets whether the domain is bottom bool abstract_environmentt::is_bottom() const { return map.empty() && bottom; } -/*******************************************************************\ - -Function: abstract_environmentt::is_top - - Inputs: - - Outputs: - - Purpose: Gets whether the domain is top - -\*******************************************************************/ - +/// Function: abstract_environmentt::is_top +/// +/// Gets whether the domain is top bool abstract_environmentt::is_top() const { return map.empty() && !bottom; } -/*******************************************************************\ - -Function: abstract_environmentt::output - - Inputs: - out - the stream to write to - ai - the abstract interpreter that contains this domain - ns - the current namespace - - Outputs: None - - Purpose: Print out all the values in the abstract object map - -\*******************************************************************/ - +/// Function: abstract_environmentt::output +/// +/// \param out: the stream to write to +/// \param ai: the abstract interpreter that contains this domain +/// \param ns: the current namespace +/// +/// Print out all the values in the abstract object map void abstract_environmentt::output( std::ostream &out, const ai_baset &ai, @@ -652,18 +558,9 @@ void abstract_environmentt::output( out << "}\n"; } -/*******************************************************************\ - -Function: abstract_environmentt::verify - - Inputs: - - Outputs: - - Purpose: Check there aren't any null pointer mapped values - -\*******************************************************************/ - +/// Function: abstract_environmentt::verify +/// +/// Check there aren't any null pointer mapped values bool abstract_environmentt::verify() const { decltype(map)::viewt view; @@ -700,44 +597,33 @@ abstract_object_pointert abstract_environmentt::eval_expression( return eval_obj->expression_transform(e, operands, *this, ns); } -/*******************************************************************\ - -Function: abstract_environmentt::erase - - Inputs: A symbol to delete from the map - - Outputs: - - Purpose: Delete a symbol from the map. This is necessary if the - symbol falls out of scope and should no longer be tracked. - -\*******************************************************************/ - +/// Function: abstract_environmentt::erase +/// +/// \param expr: A symbol to delete from the map +/// +/// +/// Delete a symbol from the map. This is necessary if the +/// symbol falls out of scope and should no longer be tracked. void abstract_environmentt::erase(const symbol_exprt &expr) { map.erase_if_exists(expr.get_identifier()); } -/*******************************************************************\ - -Function: abstract_environmentt::environment_diff - - Inputs: Two abstract_environmentt's that need to be intersected for, - so that we can find symbols that have changed between - different domains. - - Outputs: An std::vector containing the symbols that are present in - both environments. - - Purpose: For our implementation of variable sensitivity domains, we - need to be able to efficiently find symbols that have changed - between different domains. To do this, we need to be able - to quickly find which symbols have new written locations, - which we do by finding the intersection between two different - domains (environments). - -\*******************************************************************/ - +/// Function: abstract_environmentt::environment_diff +/// +/// Inputs: Two abstract_environmentt's that need to be intersected for, +/// so that we can find symbols that have changed between +/// different domains. +/// +/// Outputs: An std::vector containing the symbols that are present in +/// both environments. +/// +/// Purpose: For our implementation of variable sensitivity domains, we +/// need to be able to efficiently find symbols that have changed +/// between different domains. To do this, we need to be able +/// to quickly find which symbols have new written locations, +/// which we do by finding the intersection between two different +/// domains (environments). std::vector abstract_environmentt::modified_symbols( const abstract_environmentt &first, diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 1c73ef9b845..605ccbf38ec 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -6,6 +6,14 @@ \*******************************************************************/ +/// \file +/// An abstract version of a program environment. Each variable has +/// an abstract object rather than a value. If these are top then +/// they are not explicitly stored so that the memory used is +/// proportional to what is known rather than just the number of +/// variables. +/// Note the use of sharing_mapt is critical for scalability. + #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_ENVIROMENT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_ENVIROMENT_H @@ -25,7 +33,7 @@ class abstract_environmentt public: using map_keyt = irep_idt; abstract_environmentt(); - // These three are really the heart of the method + /// These three are really the heart of the method virtual abstract_object_pointert eval(const exprt &expr, const namespacet &ns) const; virtual bool assign( @@ -57,9 +65,9 @@ class abstract_environmentt 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 + /// 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(); diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 622f9e61218..e82eeba5ecd 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -22,40 +22,22 @@ #include "abstract_object.h" -/*******************************************************************\ - -Function: abstract_objectt::abstract_objectt - - Inputs: - type - the type the abstract_object is representing - - Outputs: - - Purpose: - -\*******************************************************************/ - +/// Function: abstract_objectt::abstract_objectt +/// +/// \param type: the type the abstract_object is representing abstract_objectt::abstract_objectt(const typet &type) : t(type), bottom(false), top(true) { } -/*******************************************************************\ - -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 - -\*******************************************************************/ - +/// Function: abstract_objectt::abstract_objectt +/// +/// \param type: the type the abstract_object is representing +/// \param top: is the abstract_object starting as top +/// \param bottom: is the abstract_object starting as bottom +/// +/// 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) : t(type), bottom(bottom), top(top) { @@ -90,57 +72,38 @@ abstract_objectt::abstract_objectt( { } -/*******************************************************************\ - -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. - -\*******************************************************************/ +/// Function: abstract_objectt::type +/// +/// \return The program type this abstract object represents +/// +/// Get the real type of the variable this abstract object is representing. const typet &abstract_objectt::type() const { return t; } -/*******************************************************************\ - -Function: abstract_objectt::merge - - Inputs: - other - The object to merge with this - - Outputs: Returns the result of the merge. - - Purpose: Create a new abstract object that is the result of the merge, unless - the object would be unchanged, then would return itself. - -\*******************************************************************/ - +/// Function: abstract_objectt::merge +/// +/// \param other: The object to merge with this +/// +/// \return Returns the result of the merge. +/// +/// 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::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. - -\*******************************************************************/ - +/// Function: abstract_objectt::abstract_object_merge +/// +/// \param other: The object to merge with this +/// +/// \return Returns the result of the abstract object. +/// +/// 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 { @@ -210,22 +173,15 @@ abstract_object_pointert abstract_objectt::abstract_object_meet_internal( return shared_from_this(); } -/*******************************************************************\ - -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. - -\*******************************************************************/ - +/// Function: abstract_objectt::expression_transform +/// +/// \param expr: the expression to evaluate and find the result of it. this will +/// be the symbol referred to be op0() +/// +/// \return Returns the abstract_object representing the result of this expression +/// to the maximum precision available. +/// +/// To try and resolve different expressions with the maximum level of precision available. abstract_object_pointert abstract_objectt::expression_transform( const exprt &expr, const std::vector &operands, @@ -304,36 +260,22 @@ abstract_object_pointert abstract_objectt::write( return environment.abstract_object_factory(type(), ns, true); } -/*******************************************************************\ - -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 - -\*******************************************************************/ - +/// Function: abstract_objectt::is_top +/// +/// \return Returns true if the abstract object is representing the top (i.e. we +/// don't know anything about the value). +/// +/// 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 - -\*******************************************************************/ - +/// Function: abstract_objectt::is_bottom +/// +/// \return Returns true if the abstract object is representing the bottom. +/// +/// Find out if the abstract object is bottom bool abstract_objectt::is_bottom() const { return bottom; @@ -347,43 +289,28 @@ bool abstract_objectt::verify() const return !(top && 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. - -\*******************************************************************/ - +/// Function: abstract_objectt::to_constant +/// +/// \return Returns an exprt representing the value if the value is known and +/// constant. Otherwise returns the nil expression +/// +/// 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 - the abstract interpreter that contains the abstract domain - (that contains the object ... ) - ns - the current namespace - - Outputs: - - Purpose: Print the value of the abstract object - -\*******************************************************************/ - +/// Function: abstract_objectt::output +/// +/// \param out: the stream to write to +/// \param ai: the abstract interpreter that contains the abstract domain +/// (that contains the object ... ) +/// \param ns: the current namespace +/// +/// Print the value of the abstract object void abstract_objectt::output( std::ostream &out, const ai_baset &ai, @@ -403,25 +330,18 @@ void abstract_objectt::output( } } -/*******************************************************************\ - -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. - - -\*******************************************************************/ - +/// Function: abstract_objectt::merge +/// +/// \param 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 +/// \param op2: the second abstract object to merge +/// +/// \return 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 +/// +/// Clones the first parameter and merges it with the second. abstract_object_pointert abstract_objectt::merge( abstract_object_pointert op1, abstract_object_pointert op2, @@ -436,20 +356,14 @@ abstract_object_pointert abstract_objectt::merge( 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 - -\*******************************************************************/ - +/// Function: abstract_objectt::should_use_base_merge +/// +/// \param other: the object being merged with +/// +/// \return Returns true if the base class is capable of doing a complete merge +/// +/// 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 { diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index f1f1cb6ed23..55737724d47 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -4,23 +4,25 @@ 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. - \*******************************************************************/ + +/// \file +/// 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 @@ -50,23 +52,22 @@ class namespacet; return internal_abstract_object_pointert(new current_typet(*this)); \ } -/* 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 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. - */ +/// 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 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 using sharing_ptrt = std::shared_ptr; // NOLINT(*) @@ -104,7 +105,7 @@ class abstract_objectt : public std::enable_shared_from_this const abstract_environmentt &env, const namespacet &ns) const; - // Interface for transforms + /// Interface for transforms virtual abstract_object_pointert expression_transform( const exprt &expr, const std::vector &operands, @@ -154,9 +155,9 @@ class abstract_objectt : public std::enable_shared_from_this */ virtual bool has_been_modified(const abstract_object_pointert before) const { - // Default implementation, with no other information to go on - // falls back to relying on copy-on-write and pointer inequality - // to indicate if an abstract_objectt has been modified + /// Default implementation, with no other information to go on + /// falls back to relying on copy-on-write and pointer inequality + /// to indicate if an abstract_objectt has been modified return this != before.get(); }; @@ -238,7 +239,7 @@ class abstract_objectt : public std::enable_shared_from_this } private: - // To enforce copy-on-write these are private and have read-only accessors + /// To enforce copy-on-write these are private and have read-only accessors typet t; bool bottom; bool top; diff --git a/src/analyses/variable-sensitivity/abstract_object_statistics.h b/src/analyses/variable-sensitivity/abstract_object_statistics.h index d2d75c2624a..133b11ff38f 100644 --- a/src/analyses/variable-sensitivity/abstract_object_statistics.h +++ b/src/analyses/variable-sensitivity/abstract_object_statistics.h @@ -6,6 +6,9 @@ Author: Hannes Steffenhagen \*******************************************************************/ +/// \file +/// Statistics gathering for the variable senstivity domain + #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_STATISTICS_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_OBJECT_STATISTICS_H diff --git a/src/analyses/variable-sensitivity/abstract_value.cpp b/src/analyses/variable-sensitivity/abstract_value.cpp index 2000a0e8a77..52c2c35879d 100644 --- a/src/analyses/variable-sensitivity/abstract_value.cpp +++ b/src/analyses/variable-sensitivity/abstract_value.cpp @@ -13,59 +13,34 @@ #include "abstract_value.h" -/*******************************************************************\ - -Function: abstract_valuet::abstract_valuet - - Inputs: - type - the type the abstract_value is representing - - Outputs: - - Purpose: - -\*******************************************************************/ - +/// Function: abstract_valuet::abstract_valuet +/// +/// \param type: the type the abstract_value is representing +/// 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 - -\*******************************************************************/ - +/// Function: abstract_valuet::abstract_valuet +/// +/// \param type: the type the abstract_value is representing +/// \param top: is the abstract_value starting as top +/// \param bottom: is the abstract_value starting as bottom +/// +/// 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: - 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 - -\*******************************************************************/ - +/// Function: abstract_valuet::abstract_valuet +/// +/// \param expr: the expression to use as the starting pointer for an abstract object +/// \param environment: The environment this abstract object is being created in +/// \param ns: the namespace +/// +/// Construct an abstract value from the expression abstract_valuet::abstract_valuet( const exprt &expr, const abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/abstract_value.h b/src/analyses/variable-sensitivity/abstract_value.h index c0c819e36d0..d5a54707459 100644 --- a/src/analyses/variable-sensitivity/abstract_value.h +++ b/src/analyses/variable-sensitivity/abstract_value.h @@ -5,6 +5,10 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ + +/// \file +/// The parent class of all abstractions that represent a base type + #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ABSTRACT_VALUE_H #define 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 1e4b8e7c5fb..e124f277707 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -11,41 +11,23 @@ #include #include -/*******************************************************************\ - -Function: array_abstract_objectt::array_abstract_objectt - - Inputs: - type - the type the abstract_object is representing - - Outputs: - - Purpose: - -\*******************************************************************/ - +/// Function: array_abstract_objectt::array_abstract_objectt +/// +/// \param type: the type the abstract_object is representing array_abstract_objectt::array_abstract_objectt(const typet &t) : abstract_objectt(t) { PRECONDITION(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 - -\*******************************************************************/ - +/// Function: array_abstract_objectt::array_abstract_objectt +/// +/// \param type: the type the abstract_object is representing +/// \param top: is the abstract_object starting as top +/// \param bottom: is the abstract_object starting as bottom +/// +/// 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, @@ -55,21 +37,11 @@ array_abstract_objectt::array_abstract_objectt( PRECONDITION(t.id() == ID_array); } -/*******************************************************************\ - -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: - - Purpose: - -\*******************************************************************/ - +/// Function: array_abstract_objectt::array_abstract_objectt +/// +/// \param expr: the expression to use as the starting pointer for an abstract object +/// \param environment: the environment the abstract object is being created in +/// \param ns: the namespace array_abstract_objectt::array_abstract_objectt( const exprt &e, const abstract_environmentt &environment, @@ -127,21 +99,15 @@ abstract_object_pointert array_abstract_objectt::write( environment, ns, stack, to_index_expr(specifier), value, merging_write); } -/*******************************************************************\ - -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. - -\*******************************************************************/ - +/// Function: array_abstract_objectt::read_index +/// +/// \param env: the environment +/// \param index: the expression used to access the specific value in the array +/// +/// \return An abstract object representing the value in the array +/// +/// 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, @@ -155,28 +121,22 @@ abstract_object_pointert array_abstract_objectt::read_index( return env.abstract_object_factory(subtype, ns, !is_bottom(), is_bottom()); } -/*******************************************************************\ - -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 - 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. - -\*******************************************************************/ - +/// Function: array_abstract_objectt::write_index +/// +/// \param environment: the abstract environment +/// \param ns: the namespace +/// \param stack: the remaining stack of expressions on the LHS to evaluate +/// \param index_expr: the expression uses to access a specific index +/// \param value: the value we are trying to assign to that value in the array +/// \param merging_write: ? +/// +/// \return 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. +/// +/// 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 namespacet &ns, diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index a73e535c3dd..44a23a355dc 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -5,6 +5,10 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ + +/// \file +/// The base type of all abstract array representations + #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_ARRAY_ABSTRACT_OBJECT_H #define 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 f10b5fb135d..5f208852783 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -170,21 +170,14 @@ void constant_abstract_valuet::output( } } -/*******************************************************************\ - -Function: constant_abstract_valuet::merge - - Inputs: - other - the abstract object to merge with - - 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 - - -\*******************************************************************/ - +/// Function: constant_abstract_valuet::merge +/// +/// \param other: the abstract object to merge with +/// +/// \return Returns the result of the merge +/// +/// Attempts to do a constant/constant merge if both are constants, +/// otherwise falls back to the parent merge abstract_object_pointert constant_abstract_valuet::merge(abstract_object_pointert other) const { @@ -201,21 +194,15 @@ constant_abstract_valuet::merge(abstract_object_pointert other) const } } -/*******************************************************************\ - -Function: constant_abstract_valuet::merge_constant_constant - - Inputs: - other - the abstract object to merge with - - 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 - -\*******************************************************************/ - +/// Function: constant_abstract_valuet::merge_constant_constant +/// +/// \param other: the abstract object to merge with +/// +/// \return 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. +/// +/// Merges another constant abstract value into this one abstract_object_pointert constant_abstract_valuet::merge_constant_constant( constant_abstract_value_pointert other) const { diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 9c54aab50a7..c588ed17613 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -5,6 +5,10 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ + +/// \file +/// An abstraction of a single value that just stores a constant. + #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ABSTRACT_VALUE_H #define 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 b9543022d6c..4f6ab712924 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -14,41 +14,23 @@ #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: - -\*******************************************************************/ - +/// Function: constant_array_abstract_objectt::constant_array_abstract_objectt +/// +/// \param type: the type the abstract_object is representing constant_array_abstract_objectt::constant_array_abstract_objectt(typet type) : array_abstract_objectt(type) { DATA_INVARIANT(verify(), "Structural invariants maintained"); } -/*******************************************************************\ - -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 - -\*******************************************************************/ - +/// Function: constant_array_abstract_objectt::constant_array_abstract_objectt +/// +/// \param type: the type the abstract_object is representing +/// \param top: is the abstract_object starting as top +/// \param bottom: is the abstract_object starting as bottom +/// +/// 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, @@ -58,21 +40,11 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( DATA_INVARIANT(verify(), "Structural invariants maintained"); } -/*******************************************************************\ - -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: - -\*******************************************************************/ - +/// Function: constant_array_abstract_objectt::constant_array_abstract_objectt +/// +/// \param expr: the expression to use as the starting pointer for an abstract object +/// \param environment: the environment the abstract object is being created in +/// \param ns: the namespace constant_array_abstract_objectt::constant_array_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, @@ -92,21 +64,14 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( DATA_INVARIANT(verify(), "Structural invariants maintained"); } -/*******************************************************************\ - -Function: constant_array_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 - -\*******************************************************************/ - +/// Function: constant_array_abstract_objectt::verify +/// +/// \return Returns true if the struct is valid +/// +/// 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 constant_array_abstract_objectt::verify() const { // Either the object is top or bottom (=> map empty) @@ -124,20 +89,14 @@ void constant_array_abstract_objectt::make_top_internal() map.clear(); } -/*******************************************************************\ - -Function: constant_array_abstract_objectt::merge - - Inputs: - other - The object to merge in - - 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 - -\*******************************************************************/ - +/// Function: constant_array_abstract_objectt::merge +/// +/// \param other: The object to merge in +/// +/// \return Returns the result of the merge. +/// +/// Tries to do an array/array merge if merging with a constant array +/// If it can't, falls back to parent merge abstract_object_pointert constant_array_abstract_objectt::merge(abstract_object_pointert other) const { @@ -154,21 +113,15 @@ constant_array_abstract_objectt::merge(abstract_object_pointert other) const } } -/*******************************************************************\ - -Function: constant_array_abstract_objectt::constant_array_merge - - Inputs: - other - The object to merge in - - 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 - -\*******************************************************************/ - +/// Function: constant_array_abstract_objectt::constant_array_merge +/// +/// \param other: The object to merge in +/// +/// \return 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.. +/// +/// Merges an array into this array abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( const constant_array_pointert other) const { @@ -201,24 +154,16 @@ abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( } } -/*******************************************************************\ - -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, @@ -461,21 +393,15 @@ constant_array_abstract_objectt::write_index( } } -/*******************************************************************\ - -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 - -\*******************************************************************/ - +/// Function: constant_array_abstract_objectt::get_top_entry +/// +/// \param environment: the abstract environment +/// \param ns: the namespace +/// +/// \return 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 @@ -483,21 +409,15 @@ abstract_object_pointert constant_array_abstract_objectt::get_top_entry( 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 - -\*******************************************************************/ - +/// Function: constant_array_abstract_objectt::eval_index +/// +/// \param environment: the abstract environment +/// \param ns: the namespace +/// +/// \return An abstract object pointer of type type().subtype() (i.e. the +/// type of the array's values). +/// +/// 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, diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index 287e6e524d2..ffefe29fc2c 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -5,6 +5,10 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ + +/// \file +/// An abstraction of an array value + #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_ARRAY_ABSTRACT_OBJECT_H #define 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 302f572bc70..c76eda19032 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -14,19 +14,9 @@ #include #include -/*******************************************************************\ - -Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt - - Inputs: - type - the type the abstract_object is representing - - Outputs: - - Purpose: - -\*******************************************************************/ - +/// Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt +/// +/// \param type: the type the abstract_object is representing constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( const typet &t) : pointer_abstract_objectt(t) @@ -34,22 +24,14 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( PRECONDITION(t.id() == ID_pointer); } -/*******************************************************************\ - -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 - -\*******************************************************************/ - +/// Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt +/// +/// \param type: the type the abstract_object is representing +/// \param top: is the abstract_object starting as top +/// \param bottom: is the abstract_object starting as bottom +/// +/// 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, @@ -59,38 +41,18 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( PRECONDITION(t.id() == ID_pointer); } -/*******************************************************************\ - -Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt - - Inputs: - old - the abstract object to copy from - - Outputs: - - Purpose: - -\*******************************************************************/ - +/// Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt +/// +/// \param old: the abstract object to copy from constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( const constant_pointer_abstract_objectt &old) : pointer_abstract_objectt(old), value_stack(old.value_stack) { } -/*******************************************************************\ - -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: - -\*******************************************************************/ - +/// Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt +/// +/// \param expr: the expression to use as the starting pointer for an abstract object constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( const exprt &e, const abstract_environmentt &environment, @@ -109,22 +71,16 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( } } -/*******************************************************************\ - -Function: constant_pointer_abstract_objectt::merge - - Inputs: - other - the pointer being merged - - 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 - we are trying to merge a constant pointer we use the constant pointer - constant pointer merge - -\*******************************************************************/ - +/// Function: constant_pointer_abstract_objectt::merge +/// +/// \param other: the pointer being merged +/// +/// \return Returns the result of the merge. +/// +/// 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 abstract_object_pointert constant_pointer_abstract_objectt::merge(abstract_object_pointert other) const { @@ -141,22 +97,16 @@ constant_pointer_abstract_objectt::merge(abstract_object_pointert other) const } } -/*******************************************************************\ - -Function: constant_pointer_abstract_objectt::merge_constant_pointers - - Inputs: - other - the pointer being merged - - 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. - -\*******************************************************************/ - +/// Function: constant_pointer_abstract_objectt::merge_constant_pointers +/// +/// \param other: the pointer being merged +/// +/// \return 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. +/// +/// Merges two constant pointers. If they are pointing at the same +/// value, we merge, otherwise we set to top. abstract_object_pointert constant_pointer_abstract_objectt::merge_constant_pointers( const constant_pointer_abstract_pointert other) const @@ -181,23 +131,16 @@ constant_pointer_abstract_objectt::merge_constant_pointers( } } -/*******************************************************************\ - -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 - -\*******************************************************************/ - +/// Function: constant_pointer_abstract_objectt::to_constant +/// +/// \return 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. +/// +/// To try and find a constant expression for this abstract object exprt constant_pointer_abstract_objectt::to_constant() const { if(is_top() || is_bottom()) @@ -212,22 +155,14 @@ exprt constant_pointer_abstract_objectt::to_constant() const } } -/*******************************************************************\ - -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). - -\*******************************************************************/ - +/// Function: constant_pointer_abstract_objectt::output +/// +/// \param out: the stream to write to +/// \param ai: ? +/// \param ns: ? +/// +/// 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, @@ -271,23 +206,17 @@ void constant_pointer_abstract_objectt::output( } } -/*******************************************************************\ - -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 - - 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. - -\*******************************************************************/ - +/// Function: constant_pointer_abstract_objectt::read_dereference +/// +/// \param env: the environment +/// \param ns: the namespace +/// +/// \return An abstract object representing the value this pointer is pointing +/// to +/// +/// 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 namespacet &ns) const @@ -306,31 +235,25 @@ abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( } } -/*******************************************************************\ - -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 - 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. - -\*******************************************************************/ - +/// Function: constant_pointer_abstract_objectt::write_dereference +/// +/// \param environment: the environment +/// \param ns: the namespace +/// \param stack: the remaining stack +/// \param new_value: the value to write to the dereferenced pointer +/// \param 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 +/// +/// \return A modified abstract object representing this pointer after it +/// has been written to. +/// +/// 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, diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index dc677e99f3f..73416e30874 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -5,6 +5,9 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ + +/// \file +/// An abstraction of a pointer that tracks a single pointer #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_POINTER_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_CONSTANT_POINTER_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/context_abstract_object.h b/src/analyses/variable-sensitivity/context_abstract_object.h index 453b1b756c2..c86868ca50f 100644 --- a/src/analyses/variable-sensitivity/context_abstract_object.h +++ b/src/analyses/variable-sensitivity/context_abstract_object.h @@ -11,6 +11,7 @@ #include /** + * \file * General implementation of a an abstract_objectt which can track * side information in the form of a 'context' associated with a wrapped * abstract_objectt of some other type. This class is not intended to be diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 0ea117565f7..37faea13877 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -31,19 +31,9 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( { } -/*******************************************************************\ - -Function: full_struct_abstract_objectt::struct_abstract_objectt - - Inputs: - type - the type the abstract_object is representing - - Outputs: - - Purpose: - -\*******************************************************************/ - +/// Function: full_struct_abstract_objectt::struct_abstract_objectt +/// +/// \param type: the type the abstract_object is representing full_struct_abstract_objectt::full_struct_abstract_objectt(const typet &t) : struct_abstract_objectt(t) { @@ -51,22 +41,14 @@ full_struct_abstract_objectt::full_struct_abstract_objectt(const typet &t) DATA_INVARIANT(verify(), "Structural invariants maintained"); } -/*******************************************************************\ - -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 - -\*******************************************************************/ - +/// Function: struct_abstract_objectt::struct_abstract_objectt +/// +/// \param type: the type the abstract_object is representing +/// \param top: is the abstract_object starting as top +/// \param bottom: is the abstract_object starting as bottom +/// +/// 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, @@ -77,20 +59,10 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( DATA_INVARIANT(verify(), "Structural invariants maintained"); } -/*******************************************************************\ - -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: - -\*******************************************************************/ - +/// Function: full_struct_abstract_objectt::full_struct_abstract_objectt +/// +/// \param expr: the expression to use as the starting pointer for an +/// abstract object full_struct_abstract_objectt::full_struct_abstract_objectt( const exprt &e, const abstract_environmentt &environment, @@ -121,24 +93,18 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( DATA_INVARIANT(verify(), "Structural invariants maintained"); } -/*******************************************************************\ - -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. - -\*******************************************************************/ - +/// Function: struct_abstract_objectt::read_component +/// +/// \param environment: the abstract environment +/// \param member_expr: the expression uses to access a specific component +/// +/// \return The abstract object representing the value of that +/// component. For this abstraction this will always be top +/// since we are not tracking the struct. +/// +/// 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, @@ -171,27 +137,21 @@ abstract_object_pointert full_struct_abstract_objectt::read_component( } } -/*******************************************************************\ - -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. - -\*******************************************************************/ - +/// Function: struct_abstract_objectt::write_component +/// +/// \param environment: the abstract environment +/// \param stack: the remaining stack of expressions on the LHS to evaluate +/// \param member_expr: the expression uses to access a specific component +/// \param value: the value we are trying to write to the component +/// +/// \return 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. +/// +/// 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, @@ -288,24 +248,16 @@ full_struct_abstract_objectt::write_component( } } -/*******************************************************************\ - -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= map empty) @@ -359,21 +304,15 @@ bool full_struct_abstract_objectt::verify() const return (is_top() || is_bottom()) == map.empty(); } -/*******************************************************************\ - -Function: full_struct_abstract_objectt::merge - - Inputs: - other - the other object being merged - - 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 - Otherwise we call back to the parent merge. - -\*******************************************************************/ - +/// Function: full_struct_abstract_objectt::merge +/// +/// \param other: the other object being merged +/// +/// \return Returns the result of the merge. +/// +/// 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. abstract_object_pointert full_struct_abstract_objectt::merge(abstract_object_pointert other) const { @@ -390,21 +329,15 @@ full_struct_abstract_objectt::merge(abstract_object_pointert other) const } } -/*******************************************************************\ - -Function: full_struct_abstract_objectt::merge_constant_structs - - Inputs: - other - the other object being merged - - 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 - -\*******************************************************************/ - +/// Function: full_struct_abstract_objectt::merge_constant_structs +/// +/// \param other: the other object being merged +/// +/// \return 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. +/// +/// Performs an element wise merge of the map for each struct abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( constant_struct_pointert other) const { diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index bb3ab68bdc5..56e67f10b86 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -6,6 +6,8 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ +/// \file +/// An abstraction of a structure that stores one abstract object per field #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_FULL_STRUCT_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_FULL_STRUCT_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h index ae99ad34e77..2c31cf29329 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.h +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -5,6 +5,10 @@ Author: Diffblue Ltd. \*******************************************************************/ + +/// \file +/// An interval to represent a set of possible values. + #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_INTERVAL_ABSTRACT_VALUE_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_INTERVAL_ABSTRACT_VALUE_H diff --git a/src/analyses/variable-sensitivity/interval_array_abstract_object.h b/src/analyses/variable-sensitivity/interval_array_abstract_object.h index f3f7a1b216d..e626742cd71 100644 --- a/src/analyses/variable-sensitivity/interval_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/interval_array_abstract_object.h @@ -6,6 +6,8 @@ Author: Diffblue Ltd. \*******************************************************************/ +/// \file +/// An abstraction of an array using intervals #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_INTERVAL_ARRAY_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_INTERVAL_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 e8c6e45404e..5add02e1a11 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -12,41 +12,23 @@ #include "pointer_abstract_object.h" -/*******************************************************************\ - -Function: pointer_abstract_objectt::pointer_abstract_objectt - - Inputs: - type - the type the abstract_object is representing - - Outputs: - - Purpose: - -\*******************************************************************/ - +/// Function: pointer_abstract_objectt::pointer_abstract_objectt +/// +/// \param type: the type the abstract_object is representing pointer_abstract_objectt::pointer_abstract_objectt(const typet &t) : abstract_objectt(t) { PRECONDITION(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 - -\*******************************************************************/ - +/// Function: pointer_abstract_objectt::pointer_abstract_objectt +/// +/// \param type: the type the abstract_object is representing +/// \param top: is the abstract_object starting as top +/// \param bottom: is the abstract_object starting as bottom +/// +/// 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, @@ -56,19 +38,9 @@ pointer_abstract_objectt::pointer_abstract_objectt( PRECONDITION(t.id() == ID_pointer); } -/*******************************************************************\ - -Function: pointer_abstract_objectt::pointer_abstract_objectt - - Inputs: - expr - the expression to use as the starting pointer for an abstract object - - Outputs: - - Purpose: - -\*******************************************************************/ - +/// Function: pointer_abstract_objectt::pointer_abstract_objectt +/// +/// \param expr: the expression to use as the starting pointer for an abstract object pointer_abstract_objectt::pointer_abstract_objectt( const exprt &e, const abstract_environmentt &environment, @@ -125,21 +97,15 @@ abstract_object_pointert pointer_abstract_objectt::write( return write_dereference(environment, ns, stack, value, merging_write); } -/*******************************************************************\ - -Function: pointer_abstract_objectt::read_dereference - - Inputs: - env - the environment - ns - the namespace - - 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. - -\*******************************************************************/ - +/// Function: pointer_abstract_objectt::read_dereference +/// +/// \param env: the environment +/// \param ns: the namespace +/// +/// \return An abstract object representing the value being pointed to +/// +/// 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 namespacet &ns) const @@ -150,30 +116,24 @@ abstract_object_pointert pointer_abstract_objectt::read_dereference( return env.abstract_object_factory(pointed_to_type, ns, true, false); } -/*******************************************************************\ - -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 - 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. More - precise abstractions may override this provide more precise results. - -\*******************************************************************/ - +/// Function: pointer_abstract_objectt::write_dereference +/// +/// \param environment: the abstract environment +/// \param ns: the namespace +/// \param stack: the remaining stack of expressions on the LHS to evaluate +/// \param value: the value we are trying to assign to what the pointer is +/// pointing to +/// \param 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 +/// +/// \return A modified abstract object representing this pointer after it +/// has been written to. +/// +/// 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, diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index 82829b427d7..db2ae8cf120 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -5,6 +5,8 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com \*******************************************************************/ + +/// \file The base of all pointer abstractions #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_POINTER_ABSTRACT_OBJECT_H #define 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 f8cc4bde1ed..d6587725825 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -13,41 +13,23 @@ #include "struct_abstract_object.h" -/*******************************************************************\ - -Function: struct_abstract_objectt::struct_abstract_objectt - - Inputs: - type - the type the abstract_object is representing - - Outputs: - - Purpose: - -\*******************************************************************/ - +/// Function: struct_abstract_objectt::struct_abstract_objectt +/// +/// \param type: the type the abstract_object is representing struct_abstract_objectt::struct_abstract_objectt(const typet &t) : abstract_objectt(t) { PRECONDITION(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 - -\*******************************************************************/ - +/// Function: struct_abstract_objectt::struct_abstract_objectt +/// +/// \param type: the type the abstract_object is representing +/// \param top: is the abstract_object starting as top +/// \param bottom: is the abstract_object starting as bottom +/// +/// \return 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, @@ -57,19 +39,9 @@ struct_abstract_objectt::struct_abstract_objectt( PRECONDITION(t.id() == ID_struct); } -/*******************************************************************\ - -Function: struct_abstract_objectt::struct_abstract_objectt - - Inputs: - expr - the expression to use as the starting pointer for an abstract object - - Outputs: - - Purpose: - -\*******************************************************************/ - +/// Function: struct_abstract_objectt::struct_abstract_objectt +/// +/// \param expr: the expression to use as the starting pointer for an abstract object struct_abstract_objectt::struct_abstract_objectt( const exprt &e, const abstract_environmentt &environment, @@ -127,24 +99,18 @@ abstract_object_pointert struct_abstract_objectt::write( environment, ns, stack, to_member_expr(specifier), value, merging_write); } -/*******************************************************************\ - -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. - -\*******************************************************************/ - +/// Function: struct_abstract_objectt::read_component +/// +/// \param environment: the abstract environment +/// \param member_expr: the expression uses to access a specific component +/// +/// \return The abstract object representing the value of that component. For +/// this abstraction this will always be top since we are not tracking +/// the struct. +/// +/// 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, @@ -156,26 +122,20 @@ abstract_object_pointert struct_abstract_objectt::read_component( member_expr.type(), ns, !is_bottom(), is_bottom()); } -/*******************************************************************\ - -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. - -\*******************************************************************/ - +/// Function: struct_abstract_objectt::write_component +/// +/// \param environment: the abstract environment +/// \param stack: the remaining stack of expressions on the LHS to evaluate +/// \param member_expr: the expression uses to access a specific component +/// \param value: the value we are trying to write to the component +/// +/// \return 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. +/// +/// 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( abstract_environmentt &environment, const namespacet &ns, diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index 5d2f02ffe93..88fc3c76a1d 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -6,6 +6,9 @@ \*******************************************************************/ +/// \file +/// The base of all structure abstractions + #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_STRUCT_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/union_abstract_object.cpp b/src/analyses/variable-sensitivity/union_abstract_object.cpp index a00dc8da25c..e36da4e7c74 100644 --- a/src/analyses/variable-sensitivity/union_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/union_abstract_object.cpp @@ -12,41 +12,23 @@ #include "union_abstract_object.h" -/*******************************************************************\ - -Function: union_abstract_objectt::union_abstract_objectt - - Inputs: - type - the type the abstract_object is representing - - Outputs: - - Purpose: - -\*******************************************************************/ - +/// Function: union_abstract_objectt::union_abstract_objectt +/// +/// \param type: the type the abstract_object is representing union_abstract_objectt::union_abstract_objectt(const typet &type) : abstract_objectt(type) { PRECONDITION(type.id() == ID_union); } -/*******************************************************************\ - -Function: union_abstract_objectt::union_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 - -\*******************************************************************/ - +/// Function: union_abstract_objectt::union_abstract_objectt +/// +/// \param type: the type the abstract_object is representing +/// \param top: is the abstract_object starting as top +/// \param bottom: is the abstract_object starting as bottom +/// +/// Start the abstract object at either top or bottom or neither +/// Asserts if both top and bottom are true union_abstract_objectt::union_abstract_objectt( const typet &type, bool top, @@ -56,20 +38,10 @@ union_abstract_objectt::union_abstract_objectt( PRECONDITION(type.id() == ID_union); } -/*******************************************************************\ - -Function: union_abstract_objectt::union_abstract_objectt - - Inputs: - expr - the expression to use as the starting pointer for an abstract object - environment - the environment the abstract object is going to be evaluated in. - - Outputs: - - Purpose: - -\*******************************************************************/ - +/// Function: union_abstract_objectt::union_abstract_objectt +/// +/// \param expr: the expression to use as the starting pointer for an abstract object +/// \param environment: the environment the abstract object is going to be evaluated in. union_abstract_objectt::union_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, @@ -127,24 +99,18 @@ abstract_object_pointert union_abstract_objectt::write( environment, ns, stack, to_member_expr(specifier), value, merging_write); } -/*******************************************************************\ - -Function: union_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 union. - - Purpose: A helper function to evaluate the abstract object contained - within a union. More precise abstractions may override this - to return more precise results. - -\*******************************************************************/ - +/// Function: union_abstract_objectt::read_component +/// +/// \param environment: the abstract environment +/// \param member_expr: the expression uses to access a specific component +/// +/// The abstract object representing the value of that component. For +/// this abstraction this will always be top since we are not tracking +/// the union. +/// +/// A helper function to evaluate the abstract object contained +/// within a union. More precise abstractions may override this +/// to return more precise results. abstract_object_pointert union_abstract_objectt::read_component( const abstract_environmentt &environment, const member_exprt &member_expr, @@ -154,26 +120,20 @@ abstract_object_pointert union_abstract_objectt::read_component( member_expr.type(), ns, !is_bottom(), is_bottom()); } -/*******************************************************************\ - -Function: union_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 union_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 union. - - Purpose: A helper function to evaluate writing to a component of a union. - More precise abstractions may override this to - update what they are storing for a specific component. - -\*******************************************************************/ - +/// Function: union_abstract_objectt::write_component +/// +/// \param environment: the abstract environment +/// \param stack: the remaining stack of expressions on the LHS to evaluate +/// \param member_expr: the expression uses to access a specific component +/// \param value: the value we are trying to write to the component +/// +/// \return The union_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 union. +/// +/// A helper function to evaluate writing to a component of a union. +/// More precise abstractions may override this to +/// update what they are storing for a specific component. sharing_ptrt union_abstract_objectt::write_component( abstract_environmentt &environment, const namespacet &ns, diff --git a/src/analyses/variable-sensitivity/union_abstract_object.h b/src/analyses/variable-sensitivity/union_abstract_object.h index 5bcb503446b..e7109c97592 100644 --- a/src/analyses/variable-sensitivity/union_abstract_object.h +++ b/src/analyses/variable-sensitivity/union_abstract_object.h @@ -6,6 +6,9 @@ \*******************************************************************/ +/// \file +/// The base of all union abstractions + #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_UNION_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_UNION_ABSTRACT_OBJECT_H diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h index cf9f2a048ad..fa745c83355 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.h @@ -5,6 +5,10 @@ Author: Diffblue Ltd. \*******************************************************************/ + +/// \file +/// A forked and modified version of analyses/dependence_graph.{h,cpp} +/// that uses VSD to track and generate the dependencies. #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DEPENDENCE_GRAPH_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DEPENDENCE_GRAPH_H diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index e4a5f806ddf..187db6d18d4 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -21,19 +21,16 @@ Date: April 2016 # include #endif -/*******************************************************************\ - -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 - -\*******************************************************************/ - +/// Function: variable_sensitivity_domaint::transform +/// +/// \param from: the instruction before the abstract domain +/// \param to: the instruction after the abstract domain +/// \param ai: the abstract interpreter +/// \param ns: the namespace +/// +/// \return none +/// +/// Compute the abstract transformer for a single instruction void variable_sensitivity_domaint::transform( const irep_idt &function_from, locationt from, @@ -188,18 +185,15 @@ void variable_sensitivity_domaint::transform( DATA_INVARIANT(abstract_state.verify(), "Structural invariant"); } -/*******************************************************************\ - -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 - -\*******************************************************************/ +/// Function: variable_sensitivity_domaint::output +/// +/// \param out: the output stream +/// \param ai: the abstract interpreter +/// \param ns: the namespace +/// +/// \return none +/// +/// Basic text output of the abstract domain void variable_sensitivity_domaint::output( std::ostream &out, const ai_baset &ai, @@ -208,68 +202,40 @@ void variable_sensitivity_domaint::output( abstract_state.output(out, ai, ns); } -/*******************************************************************\ - -Function: variable_sensitivity_domaint::make_bottom - - Inputs: None - - Outputs: None - - Purpose: Sets the domain to bottom (no relations). - -\*******************************************************************/ +/// Function: variable_sensitivity_domaint::make_bottom +/// +/// 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). - -\*******************************************************************/ +/// Function: variable_sensitivity_domaint::make_top +/// +/// 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. - -\*******************************************************************/ +/// Function: variable_sensitivity_domaint::make_entry +/// +/// Set up a sane entry state. void variable_sensitivity_domaint::make_entry() { abstract_state.make_top(); } -/*******************************************************************\ - -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". - -\*******************************************************************/ - +/// Function: variable_sensitivity_domaint::merge +/// +/// \param b: the other domain +/// \param from: it's preceding location +/// \param to: it's current location +/// +/// \return true if something has changed. +/// +/// Computes the join between "this" and "b". bool variable_sensitivity_domaint::merge( const variable_sensitivity_domaint &b, locationt from, @@ -287,23 +253,17 @@ bool variable_sensitivity_domaint::merge( return any_changes; } -/*******************************************************************\ - -Function: variable_sensitivity_domaint::ai_simplify - - Inputs: - condition - the expression to simplify - ns - the namespace - lhs - is the expression on the left hand side - - 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 - reduce some values to constants. - -\*******************************************************************/ - +/// Function: variable_sensitivity_domaint::ai_simplify +/// +/// \param condition: the expression to simplify +/// \param ns: the namespace +/// \param lhs: is the expression on the left hand side +/// +/// \return True if no simplification was made +/// +/// 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. bool variable_sensitivity_domaint::ai_simplify( exprt &condition, const namespacet &ns) const @@ -331,34 +291,21 @@ bool variable_sensitivity_domaint::ai_simplify( } } -/*******************************************************************\ - -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. - -\*******************************************************************/ - +/// Function: variable_sensitivity_domaint::is_bottom +/// +/// \return True if the domain is bottom (i.e. unreachable). +/// +/// Find out if the domain is currently unreachable. bool variable_sensitivity_domaint::is_bottom() const { 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 - -\*******************************************************************/ +/// Function: variable_sensitivity_domaint::is_top +/// +/// \return True if the domain is top +/// +/// Is the domain completely top at this state bool variable_sensitivity_domaint::is_top() const { return abstract_state.is_top(); @@ -374,27 +321,19 @@ std::vector variable_sensitivity_domaint::get_modified_symbols( abstract_state, other.abstract_state); } -/*******************************************************************\ - -Function: variable_sensitivity_domaint::transform_function_call - - Inputs: - from - the location to transform from which is a function call - to - the destination of the transform (potentially inside the function call) - ai - the abstract interpreter - ns - the namespace of the current state - - Outputs: - - Purpose: Used by variable_sensitivity_domaint::transform to handle - FUNCTION_CALL transforms. This is copying the values of the arguments - into new symbols corresponding to the declared parameter names. - - If the function call is opaque we currently top the return value - and the value of any things whose address is passed into the function. - -\*******************************************************************/ - +/// Function: variable_sensitivity_domaint::transform_function_call +/// +/// \param from: the location to transform from which is a function call +/// \param to: the destination of the transform (potentially inside the function call) +/// \param ai: the abstract interpreter +/// \param ns: the namespace of the current state +/// +/// Used by variable_sensitivity_domaint::transform to handle +/// FUNCTION_CALL transforms. This is copying the values of the arguments +/// into new symbols corresponding to the declared parameter names. +/// +/// If the function call is opaque we currently top the return value +/// and the value of any things whose address is passed into the function. void variable_sensitivity_domaint::transform_function_call( locationt from, locationt to, @@ -517,20 +456,14 @@ void variable_sensitivity_domaint::transform_function_call( } } -/*******************************************************************\ - -Function: variable_sensitivity_domaint::ignore_function_call_transform - - Inputs: - function_id - the name of the function being called - - Outputs: Returns true if the function should be ignored - - Purpose: Used to specify which CPROVER internal functions should be skipped - over when doing function call transforms - -\*******************************************************************/ - +/// Function: variable_sensitivity_domaint::ignore_function_call_transform +/// +/// \param function_id: the name of the function being called +/// +/// \return Returns true if the function should be ignored +/// +/// Used to specify which CPROVER internal functions should be skipped +/// over when doing function call transforms bool variable_sensitivity_domaint::ignore_function_call_transform( const irep_idt &function_id) const { diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 70593c0e4ea..0bf96503231 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -4,61 +4,62 @@ 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. +\*******************************************************************/ +/// \file +/// 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_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_DOMAIN_H @@ -80,13 +81,13 @@ class variable_sensitivity_domaint : public ai_domain_baset ai_baset &ai, const namespacet &ns) override; - // no states + /// no states void make_bottom() override; - // all states + /// all states void make_top() override; - // a reasonable entry-point state + /// a reasonable entry-point state void make_entry() override; void output(std::ostream &out, const ai_baset &ai, const namespacet &ns) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index ae48d594ada..90697baf2a1 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -12,19 +12,13 @@ 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. - -\*******************************************************************/ - +/// Function: variable_sensitivity_object_factoryt::get_abstract_object_type +/// +/// \param type: the type of the variable the abstract object is meant to represent +/// +/// \return An enum indicating the abstract object type to use. +/// +/// 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) { @@ -78,25 +72,19 @@ variable_sensitivity_object_factoryt::get_abstract_object_type(const typet type) 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. - -\*******************************************************************/ - +/// Function: variable_sensitivity_object_factoryt::get_abstract_object +/// +/// \param type: the type of the variable +/// \param top: whether the abstract object should be top in the two-value domain +/// \param bottom: whether the abstract object should be bottom in the two-value domain +/// \param e: if top and bottom are false this expression is used as the starting +/// pointer for the abstract object +/// \param ns: namespace, used when following the input type +/// +/// \return An abstract object of the appropriate type. +/// +/// Get the appropriate abstract object for the variable under +/// consideration. abstract_object_pointert variable_sensitivity_object_factoryt::get_abstract_object( const typet type, @@ -162,20 +150,12 @@ variable_sensitivity_object_factoryt::get_abstract_object( } } -/*******************************************************************\ - -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. - -\*******************************************************************/ - +/// Function: variable_sensitivity_object_factoryt::set_options +/// +/// \param options: the command line options +/// +/// 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( const vsd_configt &options) { diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index e3d7ca152bb..90864a91685 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -5,6 +5,13 @@ Author: Owen Jones owen.jones@diffblue.com \*******************************************************************/ + +/// \file +/// Tracks the user-supplied configuration for VSD and build the +/// correct type of abstract object when needed. Note this is a factory +/// within the domain and so is lower-level than the abstract domain +/// factory that is part of the ai_baset interface. + #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_OBJECT_FACTORY_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_VARIABLE_SENSITIVITY_OBJECT_FACTORY_H @@ -169,25 +176,19 @@ class variable_sensitivity_object_factoryt bool initialized; }; -/*******************************************************************\ - -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. - -\*******************************************************************/ - +/// Function: variable_sensitivity_object_factoryt::initialize_abstract_object +/// Initialize the abstract object class and return it. +/// +/// \param abstract_object_classt: the class to use for the abstract object +/// \param type: the type of the variable +/// \param top: whether the abstract object should be top in the two-value domain +/// \param bottom: whether the abstract object should be bottom in the two-value domain +/// \param e: if top and bottom are false this expression is used as the starting +/// pointer for the abstract object +/// \param ns: namespace, used when following the input type +/// +/// \return An abstract object of the appropriate type. +/// template abstract_object_pointert variable_sensitivity_object_factoryt::initialize_abstract_object( From 3a1c7ca17846cab24f8e833f6e4b9720490bae23 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 7 Sep 2020 21:00:39 +0100 Subject: [PATCH 337/342] Reformat so that comments pass linting --- .../abstract_enviroment.cpp | 24 +++++--- .../variable-sensitivity/abstract_object.cpp | 7 ++- .../variable-sensitivity/abstract_value.cpp | 3 +- .../array_abstract_object.cpp | 3 +- .../constant_array_abstract_object.cpp | 7 ++- .../constant_pointer_abstract_object.cpp | 61 +++++++------------ .../pointer_abstract_object.cpp | 9 +-- .../struct_abstract_object.cpp | 3 +- .../union_abstract_object.cpp | 6 +- .../variable_sensitivity_domain.cpp | 3 +- .../variable_sensitivity_object_factory.cpp | 13 ++-- .../variable_sensitivity_object_factory.h | 10 +-- 12 files changed, 74 insertions(+), 75 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 1243171860b..34402705310 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -259,15 +259,16 @@ bool abstract_environmentt::assign( /// Function: abstract_object_pointert abstract_environmentt::write /// -/// \param lhs: the abstract object for the left hand side of the write (i.e. the one -/// to update). +/// \param lhs: the abstract object for the left hand side of the write +/// (i.e. the one to update). /// \param rhs: the value we are trying to write to the left hand side -/// \param remaining_stack: what is left of the stack before the rhs can replace or be -/// merged with the rhs +/// \param remaining_stack: what is left of the stack before the rhs can replace +/// or be merged with the rhs /// \param ns: the namespace -/// \param merge_write: Are we 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 +/// \param merge_write: Are we 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. /// /// \return A modified version of the rhs after the write has taken place @@ -383,7 +384,8 @@ bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) /// /// \param type: the type of the object whose state should be tracked /// \param top: does the type of the object start as top -/// \param bottom: does the type of the object start as bottom in the two-value domain +/// \param bottom: does the type of the object start as bottom in +/// the two-value domain /// /// \return The abstract object that has been created /// @@ -421,8 +423,10 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( /// /// \param type: the type of the object whose state should be tracked /// \param top: does the type of the object start as top in the two-value domain -/// \param bottom: does the type of the object start as bottom in the two-value domain -/// \param expr: the starting value of the symbol if top and bottom are both false +/// \param bottom: does the type of the object start as bottom in +/// the two-value domain +/// \param expr: the starting value of the symbol if top and bottom +/// are both false /// /// \return The abstract object that has been created /// diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index e82eeba5ecd..1a058e84a92 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -178,10 +178,11 @@ abstract_object_pointert abstract_objectt::abstract_object_meet_internal( /// \param expr: the expression to evaluate and find the result of it. this will /// be the symbol referred to be op0() /// -/// \return Returns the abstract_object representing the result of this expression -/// to the maximum precision available. +/// \return Returns the abstract_object representing the result of +/// this expression to the maximum precision available. /// -/// To try and resolve different expressions with the maximum level of precision available. +/// To try and resolve different expressions with the maximum level +/// of precision available. abstract_object_pointert abstract_objectt::expression_transform( const exprt &expr, const std::vector &operands, diff --git a/src/analyses/variable-sensitivity/abstract_value.cpp b/src/analyses/variable-sensitivity/abstract_value.cpp index 52c2c35879d..cfd952615a1 100644 --- a/src/analyses/variable-sensitivity/abstract_value.cpp +++ b/src/analyses/variable-sensitivity/abstract_value.cpp @@ -36,7 +36,8 @@ abstract_valuet::abstract_valuet(const typet &type, bool top, bool bottom) /// Function: abstract_valuet::abstract_valuet /// -/// \param expr: the expression to use as the starting pointer for an abstract object +/// \param expr: the expression to use as the starting pointer for +/// an abstract object /// \param environment: The environment this abstract object is being created in /// \param ns: the namespace /// diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index e124f277707..3877ddf03c2 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -39,7 +39,8 @@ array_abstract_objectt::array_abstract_objectt( /// Function: array_abstract_objectt::array_abstract_objectt /// -/// \param expr: the expression to use as the starting pointer for an abstract object +/// \param expr: the expression to use as the starting pointer for +/// an abstract object /// \param environment: the environment the abstract object is being created in /// \param ns: the namespace array_abstract_objectt::array_abstract_objectt( diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 4f6ab712924..a49107a780a 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -42,7 +42,8 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( /// Function: constant_array_abstract_objectt::constant_array_abstract_objectt /// -/// \param expr: the expression to use as the starting pointer for an abstract object +/// \param expr: the expression to use as the starting pointer for +/// an abstract object /// \param environment: the environment the abstract object is being created in /// \param ns: the namespace constant_array_abstract_objectt::constant_array_abstract_objectt( @@ -260,8 +261,8 @@ abstract_object_pointert constant_array_abstract_objectt::read_index( /// \param stack: the remaining stack of expressions on the LHS to evaluate /// \param index_expr: the expression uses to access a specific index /// \param value: the value we are trying to assign to that value in the array -/// \param merging_write: Should this and all future writes be merged with the current -/// value +/// \param merging_write: Should this and all future writes be merged with the +/// current value /// \return The array_abstract_objectt representing the result of writing /// to a specific index. /// diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index c76eda19032..796bdb6a45f 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -14,8 +14,6 @@ #include #include -/// Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt -/// /// \param type: the type the abstract_object is representing constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( const typet &t) @@ -24,8 +22,6 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( PRECONDITION(t.id() == ID_pointer); } -/// Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt -/// /// \param type: the type the abstract_object is representing /// \param top: is the abstract_object starting as top /// \param bottom: is the abstract_object starting as bottom @@ -41,8 +37,6 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( PRECONDITION(t.id() == ID_pointer); } -/// Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt -/// /// \param old: the abstract object to copy from constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( const constant_pointer_abstract_objectt &old) @@ -50,9 +44,8 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( { } -/// Function: constant_pointer_abstract_objectt::constant_pointer_abstract_objectt -/// -/// \param expr: the expression to use as the starting pointer for an abstract object +/// \param expr: the expression to use as the starting pointer for +/// an abstract object constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( const exprt &e, const abstract_environmentt &environment, @@ -70,17 +63,14 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( clear_top(); } } - -/// Function: constant_pointer_abstract_objectt::merge -/// -/// \param other: the pointer being merged -/// -/// \return Returns the result of the merge. -/// /// 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 +/// +/// \param other: the pointer being merged +/// +/// \return Returns the result of the merge. abstract_object_pointert constant_pointer_abstract_objectt::merge(abstract_object_pointert other) const { @@ -97,16 +87,14 @@ constant_pointer_abstract_objectt::merge(abstract_object_pointert other) const } } -/// Function: constant_pointer_abstract_objectt::merge_constant_pointers +/// Merges two constant pointers. If they are pointing at the same +/// value, we merge, otherwise we set to top. /// /// \param other: the pointer being merged /// /// \return 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. -/// -/// Merges two constant pointers. If they are pointing at the same -/// value, we merge, otherwise we set to top. abstract_object_pointert constant_pointer_abstract_objectt::merge_constant_pointers( const constant_pointer_abstract_pointert other) const @@ -131,7 +119,7 @@ constant_pointer_abstract_objectt::merge_constant_pointers( } } -/// Function: constant_pointer_abstract_objectt::to_constant +/// To try and find a constant expression for this abstract object /// /// \return Returns an expression representing the value if it can. /// Returns a nil expression if it can be more than one value. @@ -140,7 +128,6 @@ constant_pointer_abstract_objectt::merge_constant_pointers( /// result of to_constant called on whatever abstract object this /// pointer is pointing to. /// -/// To try and find a constant expression for this abstract object exprt constant_pointer_abstract_objectt::to_constant() const { if(is_top() || is_bottom()) @@ -155,14 +142,12 @@ exprt constant_pointer_abstract_objectt::to_constant() const } } -/// Function: constant_pointer_abstract_objectt::output +/// Print the value of the pointer. Either NULL if nullpointer or +/// ptr -> ( output of what the pointer is pointing to). /// /// \param out: the stream to write to /// \param ai: ? /// \param ns: ? -/// -/// 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, @@ -206,17 +191,15 @@ void constant_pointer_abstract_objectt::output( } } -/// Function: constant_pointer_abstract_objectt::read_dereference +/// 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. /// /// \param env: the environment /// \param ns: the namespace /// /// \return An abstract object representing the value this pointer is pointing /// to -/// -/// 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 namespacet &ns) const @@ -235,7 +218,10 @@ abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( } } -/// Function: constant_pointer_abstract_objectt::write_dereference +/// 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. /// /// \param environment: the environment /// \param ns: the namespace @@ -243,17 +229,12 @@ abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( /// \param new_value: the value to write to the dereferenced pointer /// \param 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 +/// 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 /// /// \return A modified abstract object representing this pointer after it /// has been written to. -/// -/// 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, diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index 5add02e1a11..8b694518cb8 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -40,7 +40,8 @@ pointer_abstract_objectt::pointer_abstract_objectt( /// Function: pointer_abstract_objectt::pointer_abstract_objectt /// -/// \param expr: the expression to use as the starting pointer for an abstract object +/// \param expr: the expression to use as the starting pointer for +/// an abstract object pointer_abstract_objectt::pointer_abstract_objectt( const exprt &e, const abstract_environmentt &environment, @@ -125,9 +126,9 @@ abstract_object_pointert pointer_abstract_objectt::read_dereference( /// pointing to /// \param 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 +/// 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 /// /// \return A modified abstract object representing this pointer after it /// has been written to. diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index d6587725825..3ae827b4f32 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -41,7 +41,8 @@ struct_abstract_objectt::struct_abstract_objectt( /// Function: struct_abstract_objectt::struct_abstract_objectt /// -/// \param expr: the expression to use as the starting pointer for an abstract object +/// \param expr: the expression to use as the starting pointer for +/// an abstract object struct_abstract_objectt::struct_abstract_objectt( const exprt &e, const abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/union_abstract_object.cpp b/src/analyses/variable-sensitivity/union_abstract_object.cpp index e36da4e7c74..215d8442ad3 100644 --- a/src/analyses/variable-sensitivity/union_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/union_abstract_object.cpp @@ -40,8 +40,10 @@ union_abstract_objectt::union_abstract_objectt( /// Function: union_abstract_objectt::union_abstract_objectt /// -/// \param expr: the expression to use as the starting pointer for an abstract object -/// \param environment: the environment the abstract object is going to be evaluated in. +/// \param expr: the expression to use as the starting pointer for +/// an abstract object +/// \param environment: the environment the abstract object is going +/// to be evaluated in. union_abstract_objectt::union_abstract_objectt( const exprt &expr, 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 187db6d18d4..31be5babf7f 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -324,7 +324,8 @@ std::vector variable_sensitivity_domaint::get_modified_symbols( /// Function: variable_sensitivity_domaint::transform_function_call /// /// \param from: the location to transform from which is a function call -/// \param to: the destination of the transform (potentially inside the function call) +/// \param to: the destination of the transform +/// (potentially inside the function call) /// \param ai: the abstract interpreter /// \param ns: the namespace of the current state /// diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 90697baf2a1..5ca467df824 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -14,7 +14,8 @@ variable_sensitivity_object_factoryt /// Function: variable_sensitivity_object_factoryt::get_abstract_object_type /// -/// \param type: the type of the variable the abstract object is meant to represent +/// \param type: the type of the variable the abstract object is +/// meant to represent /// /// \return An enum indicating the abstract object type to use. /// @@ -75,10 +76,12 @@ variable_sensitivity_object_factoryt::get_abstract_object_type(const typet type) /// Function: variable_sensitivity_object_factoryt::get_abstract_object /// /// \param type: the type of the variable -/// \param top: whether the abstract object should be top in the two-value domain -/// \param bottom: whether the abstract object should be bottom in the two-value domain -/// \param e: if top and bottom are false this expression is used as the starting -/// pointer for the abstract object +/// \param top: whether the abstract object should be top in the +/// two-value domain +/// \param bottom: whether the abstract object should be bottom in the +/// two-value domain +/// \param e: if top and bottom are false this expression is used as the +/// starting pointer for the abstract object /// \param ns: namespace, used when following the input type /// /// \return An abstract object of the appropriate type. diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index 90864a91685..29d058b6f6a 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -181,10 +181,12 @@ class variable_sensitivity_object_factoryt /// /// \param abstract_object_classt: the class to use for the abstract object /// \param type: the type of the variable -/// \param top: whether the abstract object should be top in the two-value domain -/// \param bottom: whether the abstract object should be bottom in the two-value domain -/// \param e: if top and bottom are false this expression is used as the starting -/// pointer for the abstract object +/// \param top: whether the abstract object should be top in the +/// two-value domain +/// \param bottom: whether the abstract object should be bottom in the +/// two-value domain +/// \param e: if top and bottom are false this expression is used as the +/// starting pointer for the abstract object /// \param ns: namespace, used when following the input type /// /// \return An abstract object of the appropriate type. From 0d80676ec524280153206715dc376b0ee9dfec07 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 7 Sep 2020 22:50:34 +0100 Subject: [PATCH 338/342] Apply Peter Schrammel's review comments --- .../abstract_enviroment.cpp | 2 +- .../variable-sensitivity/abstract_object.h | 2 +- .../array_abstract_object.cpp | 4 +- .../constant_array_abstract_object.cpp | 2 +- .../data_dependency_context.cpp | 4 +- .../full_struct_abstract_object.cpp | 3 +- .../three_way_merge_abstract_interpreter.cpp | 100 +----------------- .../variable_sensitivity_domain.h | 17 +-- .../write_location_context.cpp | 6 +- .../variable-sensitivity/write_stack.cpp | 2 +- .../variable-sensitivity/write_stack.h | 2 +- .../write_stack_entry.cpp | 2 +- .../variable-sensitivity/write_stack_entry.h | 2 +- .../abstract_object/merge.cpp | 2 +- .../constant_abstract_value/merge.cpp | 2 +- .../constant_array_abstract_object/merge.cpp | 2 +- unit/analyses/variable-sensitivity/eval.cpp | 2 +- .../full_struct_abstract_object/merge.cpp | 2 +- .../interval_abstract_value/meet.cpp | 2 +- .../last_written_location.cpp | 2 +- 20 files changed, 32 insertions(+), 130 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 34402705310..ff93840731d 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -140,7 +140,7 @@ abstract_environmentt::eval(const exprt &expr, const namespacet &ns) const /// 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 +/// As abstractions may split the assignment into multiple writes (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 diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 55737724d47..523bca8a8ad 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -10,7 +10,7 @@ /// 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 +/// bottom). Within the hierarchy 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 diff --git a/src/analyses/variable-sensitivity/array_abstract_object.cpp b/src/analyses/variable-sensitivity/array_abstract_object.cpp index 3877ddf03c2..29ce3c51008 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -131,9 +131,9 @@ abstract_object_pointert array_abstract_objectt::read_index( /// \param value: the value we are trying to assign to that value in the array /// \param merging_write: ? /// -/// \return The struct_abstract_objectt representing the result of writing +/// \return The array_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. +/// as we are not tracking the value in the array. /// /// A helper function to evaluate writing to a component of a struct. /// More precise abstractions may override this to diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index a49107a780a..7e5cf2bc148 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -490,7 +490,7 @@ void constant_array_abstract_objectt::get_statistics( array_abstract_objectt::get_statistics(statistics, visited, env, ns); shared_array_mapt::viewt view; map.get_view(view); - for(auto const &object : view) + for(const auto &object : view) { if(visited.find(object.second) == visited.end()) { diff --git a/src/analyses/variable-sensitivity/data_dependency_context.cpp b/src/analyses/variable-sensitivity/data_dependency_context.cpp index 86c335ec9ee..f647bdc958b 100644 --- a/src/analyses/variable-sensitivity/data_dependency_context.cpp +++ b/src/analyses/variable-sensitivity/data_dependency_context.cpp @@ -210,7 +210,7 @@ abstract_object_pointert data_dependency_contextt::write( * \param update_sub_elements if true, propogate the update operation to any * children of this abstract object * - * \return a clone of this abstract object with it's location context + * \return a clone of this abstract object with its location context * updated */ abstract_object_pointert data_dependency_contextt::update_location_context( @@ -280,7 +280,7 @@ data_dependency_contextt::merge(abstract_object_pointert other) const /** * Helper function for abstract_objectt::abstract_object_merge to perform any - * additional actions after the base abstract_object_merge has completed it's + * additional actions after the base abstract_object_merge has completed its * actions but immediately prior to it returning. As such, this function gives * the ability to perform additional work for a merge. * diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 37faea13877..30e8a8b6675 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -76,13 +76,12 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( bool did_initialize_values = false; auto struct_type_it = struct_type_def.components().begin(); for(auto param_it = e.operands().begin(); param_it != e.operands().end(); - ++param_it) + ++param_it, ++struct_type_it) { map.insert_or_replace( struct_type_it->get_name(), environment.abstract_object_factory(param_it->type(), *param_it, ns)); did_initialize_values = true; - ++struct_type_it; } if(did_initialize_values) diff --git a/src/analyses/variable-sensitivity/three_way_merge_abstract_interpreter.cpp b/src/analyses/variable-sensitivity/three_way_merge_abstract_interpreter.cpp index d5aea6807a0..0a63c04995d 100644 --- a/src/analyses/variable-sensitivity/three_way_merge_abstract_interpreter.cpp +++ b/src/analyses/variable-sensitivity/three_way_merge_abstract_interpreter.cpp @@ -132,7 +132,7 @@ bool ai_three_way_merget::visit_edge_function_call( ns); // TODO : this is probably needed to avoid three_way_merge modifying one of - // it's arguments as it goes. A better solution would be to refactor + // its arguments as it goes. A better solution would be to refactor // merge_three_way_function_return. const std::unique_ptr ptr_s_working_copy( make_temporary_state(s_working)); @@ -155,101 +155,3 @@ bool ai_three_way_merget::visit_edge_function_call( return new_data; } - -#if 0 - // This is the edge from function end to return site. - - { - if(end_state.is_bottom()) - return false; // function exit point not reachable - - working_sett working_set; // Redundant; visit will add l_return - -- return visit_edge( -- f_it->first, l_end, calling_function_id, l_return, ns, working_set); -+ const std::unique_ptr tmp_state(make_temporary_state(end_state)); -+ tmp_state->transform(f_it->first, l_end, f_it->first, l_return, *this, ns); -+ -+ const std::unique_ptr pre_merge_state{ -+ make_temporary_state(*tmp_state)}; -+ -+ const locationt l_begin = goto_function.body.instructions.begin(); -+ tmp_state->merge_three_way_function_return( -+ get_state(l_call), get_state(l_begin), *pre_merge_state, ns); -+ -+ return merge(*tmp_state, l_end, l_return); - } - -#endif - -#if 0 -bool ai_baset::visit_edge( - const irep_idt &function_id, - trace_ptrt p, - const irep_idt &to_function_id, - locationt to_l, - trace_ptrt caller_history, - const namespacet &ns, - working_sett &working_set) -{ - // We only care about the return cases - if (caller_history == ai_history_baset::no_caller_history) { - return ai_recursive_interproceduralt::visit_edge(function_id, p, to_function_id, to_l, caller_history, ns, working_set); - } - - // There are four histories / locations / domains we care about - // In chronological order... - - trace_ptr call_site_history = caller_history; - statet &call_site_state = get_state(call_site_history); - locationt call_site_location = call_site_history.current_location(); - INVARIANT(call_site_location->is_function_call(), "caller_history implies that is is a function call"); - - trace_ptr callee_start_history = TBD; - statet &callee_start_state = get_state(callee_start_history); - locationt callee_start_location = callee_start_history.current_location(); - - trace_ptr callee_end_history = p; - statet &callee_end_state = get_state(callee_end_history); - locationt callee_end_location = callee_end_history.current_location(); - INVARIANT(callee_end_location->is_end_function(), "TBD"); - - trace_ptr return_site_history = STEP; - statet &return_site_state = get_state(return_site_history); - locationt return_site_location = to_l; - INVARIANT(std::next(call_site_location) == to_l, "TBD"); - - - - // Has history taught us not to step here... - auto next = - p->step(to_l, *(storage->abstract_traces_before(to_l)), caller_history); - if(next.first == ai_history_baset::step_statust::BLOCKED) - return false; - trace_ptrt to_p = next.second; - - // Abstract domains are mutable so we must copy before we transform - statet ¤t = get_state(p); - - std::unique_ptr tmp_state(make_temporary_state(current)); - statet &new_values = *tmp_state; - - // Apply transformer - new_values.transform(function_id, p, to_function_id, to_p, *this, ns); - - // Expanding a domain means that it has to be analysed again - // Likewise if the history insists that it is a new trace - // (assuming it is actually reachable). - if( - merge(new_values, p, to_p) || - (next.first == ai_history_baset::step_statust::NEW && - !new_values.is_bottom())) - { - put_in_working_set(working_set, to_p); - return true; - } - - return false; -} - -#endif diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 0bf96503231..89453b52251 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -8,14 +8,15 @@ /// \file /// 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: +/// pointers. interval_domaint and constant_propagator_domaint +/// 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. diff --git a/src/analyses/variable-sensitivity/write_location_context.cpp b/src/analyses/variable-sensitivity/write_location_context.cpp index 46c851d82a0..41b501969a3 100644 --- a/src/analyses/variable-sensitivity/write_location_context.cpp +++ b/src/analyses/variable-sensitivity/write_location_context.cpp @@ -15,13 +15,13 @@ /** * Update the location context for an abstract object, potentially - * propogating the update to any children of this abstract object. + * propagating the update to any children of this abstract object. * * \param locations the set of locations to be updated * \param update_sub_elements if true, propogate the update operation to any * children of this abstract object * - * \return a clone of this abstract object with it's location context + * \return a clone of this abstract object with its location context * updated */ abstract_object_pointert write_location_contextt::update_location_context( @@ -152,7 +152,7 @@ write_location_contextt::merge(abstract_object_pointert other) const /** * Helper function for abstract_objectt::abstract_object_merge to perform any - * additional actions after the base abstract_object_merge has completed it's + * additional actions after the base abstract_object_merge has completed its * actions but immediately prior to it returning. As such, this function gives * the ability to perform additional work for a merge. * diff --git a/src/analyses/variable-sensitivity/write_stack.cpp b/src/analyses/variable-sensitivity/write_stack.cpp index 3bbed827246..c270ef4bfe9 100644 --- a/src/analyses/variable-sensitivity/write_stack.cpp +++ b/src/analyses/variable-sensitivity/write_stack.cpp @@ -2,7 +2,7 @@ Module: Variable Sensitivity Domain - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited. \*******************************************************************/ diff --git a/src/analyses/variable-sensitivity/write_stack.h b/src/analyses/variable-sensitivity/write_stack.h index 6b365346c5d..b43521afda5 100644 --- a/src/analyses/variable-sensitivity/write_stack.h +++ b/src/analyses/variable-sensitivity/write_stack.h @@ -2,7 +2,7 @@ Module: Variable Sensitivity Domain - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited. \*******************************************************************/ diff --git a/src/analyses/variable-sensitivity/write_stack_entry.cpp b/src/analyses/variable-sensitivity/write_stack_entry.cpp index da7cfc239d4..8d98ea78c42 100644 --- a/src/analyses/variable-sensitivity/write_stack_entry.cpp +++ b/src/analyses/variable-sensitivity/write_stack_entry.cpp @@ -2,7 +2,7 @@ Module: Analyses Variable Sensitivity - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited. \*******************************************************************/ diff --git a/src/analyses/variable-sensitivity/write_stack_entry.h b/src/analyses/variable-sensitivity/write_stack_entry.h index 5d58548aaa4..53efb9d5eaf 100644 --- a/src/analyses/variable-sensitivity/write_stack_entry.h +++ b/src/analyses/variable-sensitivity/write_stack_entry.h @@ -2,7 +2,7 @@ Module: Analyses Variable Sensitivity - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited. \*******************************************************************/ diff --git a/unit/analyses/variable-sensitivity/abstract_object/merge.cpp b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp index 8204a87926f..2c18baf656e 100644 --- a/unit/analyses/variable-sensitivity/abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/abstract_object/merge.cpp @@ -2,7 +2,7 @@ Module: Unit tests for variable/sensitivity/abstract_object::merge - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited. \*******************************************************************/ diff --git a/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp index 30e73797395..1447da92a69 100644 --- a/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_abstract_value/merge.cpp @@ -2,7 +2,7 @@ Module: Unit tests for constant_abstract_valuet::merge - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited. \*******************************************************************/ 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 86b6597239b..540bc5fc98e 100644 --- a/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/constant_array_abstract_object/merge.cpp @@ -2,7 +2,7 @@ Module: Unit tests for constant_array_abstract_object::merge - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited. \*******************************************************************/ diff --git a/unit/analyses/variable-sensitivity/eval.cpp b/unit/analyses/variable-sensitivity/eval.cpp index 36eb2a369bf..3a0e19f3edb 100644 --- a/unit/analyses/variable-sensitivity/eval.cpp +++ b/unit/analyses/variable-sensitivity/eval.cpp @@ -1,4 +1,4 @@ -// Copyright 2016-2020 Diffblue Limited. All Rights Reserved. +// Copyright 2016-2020 Diffblue Limited. #include #include 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 ed0a701a05c..efaead79969 100644 --- a/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp +++ b/unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp @@ -2,7 +2,7 @@ Module: Unit tests for full_struct_abstract_object::merge - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited. \*******************************************************************/ diff --git a/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp b/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp index 3e7b4088a8c..6d9499818a6 100644 --- a/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp +++ b/unit/analyses/variable-sensitivity/interval_abstract_value/meet.cpp @@ -2,7 +2,7 @@ Module: Unit tests for interval_abstract_valuet::meet - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited. \*******************************************************************/ diff --git a/unit/analyses/variable-sensitivity/last_written_location.cpp b/unit/analyses/variable-sensitivity/last_written_location.cpp index 7769f2d631c..7aa3d519a93 100644 --- a/unit/analyses/variable-sensitivity/last_written_location.cpp +++ b/unit/analyses/variable-sensitivity/last_written_location.cpp @@ -2,7 +2,7 @@ Module: Write Stack Unit Tests - Author: DiffBlue Limited. All rights reserved. + Author: DiffBlue Limited. \*******************************************************************/ From 12b273eaf990cf47a82236329ea53c7035e20bfa Mon Sep 17 00:00:00 2001 From: martin Date: Wed, 9 Sep 2020 12:27:41 +0100 Subject: [PATCH 339/342] Move doxygen comments from .cpp to .h files --- .../abstract_enviroment.cpp | 161 --------------- .../abstract_enviroment.h | 146 +++++++++++++- .../variable-sensitivity/abstract_object.cpp | 186 ------------------ .../variable-sensitivity/abstract_object.h | 179 ++++++++++++++++- .../variable-sensitivity/abstract_value.cpp | 20 -- .../variable-sensitivity/abstract_value.h | 16 ++ .../array_abstract_object.cpp | 70 ------- .../array_abstract_object.h | 64 ++++++ .../constant_abstract_value.cpp | 17 -- .../constant_abstract_value.h | 14 ++ .../constant_array_abstract_object.cpp | 107 ---------- .../constant_array_abstract_object.h | 90 +++++++++ .../full_struct_abstract_object.cpp | 94 --------- .../full_struct_abstract_object.h | 83 +++++++- .../pointer_abstract_object.cpp | 70 ------- .../pointer_abstract_object.h | 63 +++++- .../struct_abstract_object.cpp | 69 ------- .../struct_abstract_object.h | 63 +++++- .../union_abstract_object.cpp | 71 ------- .../union_abstract_object.h | 64 +++++- .../variable_sensitivity_domain.cpp | 98 --------- .../variable_sensitivity_domain.h | 80 +++++++- .../variable_sensitivity_object_factory.cpp | 29 --- .../variable_sensitivity_object_factory.h | 26 +++ 24 files changed, 873 insertions(+), 1007 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index ff93840731d..ff86d1b296c 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -27,13 +27,6 @@ # include #endif -/// Function: abstract_environmentt::eval -/// Evaluate the value of an expression relative to the current domain -/// -/// \param expr: the expression to evaluate -/// \param ns: the current namespace -/// -/// \return The abstract_object representing the value of the expression abstract_object_pointert abstract_environmentt::eval(const exprt &expr, const namespacet &ns) const { @@ -121,35 +114,6 @@ abstract_environmentt::eval(const exprt &expr, const namespacet &ns) const } } -/// Function: abstract_environmentt::assign -/// -/// \param expr: the expression to assign to -/// \param value: the value to assign to the expression -/// \param ns: the namespace -/// -/// \return A boolean, true if the assignment has changed the domain. -/// -/// 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 writes (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( const exprt &expr, const abstract_object_pointert value, @@ -257,26 +221,6 @@ bool abstract_environmentt::assign( return true; } -/// Function: abstract_object_pointert abstract_environmentt::write -/// -/// \param lhs: the abstract object for the left hand side of the write -/// (i.e. the one to update). -/// \param rhs: the value we are trying to write to the left hand side -/// \param remaining_stack: what is left of the stack before the rhs can replace -/// or be merged with the rhs -/// \param ns: the namespace -/// \param merge_write: Are we 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. -/// -/// \return A modified version of the rhs after the write has taken place -/// -/// 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, @@ -318,20 +262,6 @@ abstract_object_pointert abstract_environmentt::write( } } -/// Function: abstract_environmentt::assume -/// -/// \param expr: the expression that is to be assumed -/// \param ns: the current namespace -/// -/// \return True if the assume changed the domain. -/// -/// Reduces the domain to (an over-approximation) of the cases -/// when the the expression holds. Used to implement assume -/// statements and conditional branches. -/// It would be valid to simply return false here because it -/// is an over-approximation. We try to do better than that. -/// The better the implementation the more precise the results -/// will be. bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) { // We should only attempt to assume Boolean things @@ -380,17 +310,6 @@ bool abstract_environmentt::assume(const exprt &expr, const namespacet &ns) return false; } -/// Function: abstract_environmentt::abstract_object_factory -/// -/// \param type: the type of the object whose state should be tracked -/// \param top: does the type of the object start as top -/// \param bottom: does the type of the object start as bottom in -/// the two-value domain -/// -/// \return The abstract object that has been created -/// -/// Look at the configuration for the sensitivity and create an -/// appropriate abstract_object abstract_object_pointert abstract_environmentt::abstract_object_factory( const typet &type, const namespacet &ns, @@ -402,15 +321,6 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( type, top, bottom, empty_constant_expr, *this, ns); } -/// Function: abstract_environmentt::abstract_object_factory -/// -/// \param type: the type of the object whose state should be tracked -/// \param expr: the starting value of the symbol -/// -/// \return The abstract object that has been created -/// -/// Look at the configuration for the sensitivity and create an -/// appropriate abstract_object, assigning an appropriate value abstract_object_pointert abstract_environmentt::abstract_object_factory( const typet &type, const exprt &e, @@ -419,19 +329,6 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( return abstract_object_factory(type, false, false, e, *this, ns); } -/// Function: abstract_environmentt::abstract_object_factory -/// -/// \param type: the type of the object whose state should be tracked -/// \param top: does the type of the object start as top in the two-value domain -/// \param bottom: does the type of the object start as bottom in -/// the two-value domain -/// \param expr: the starting value of the symbol if top and bottom -/// are both false -/// -/// \return The abstract object that has been created -/// -/// 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, @@ -444,13 +341,6 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( type, top, bottom, e, environment, ns); } -/// Function: abstract_environmentt::merge -/// -/// \param env: the other environment -/// -/// \return A Boolean, true when the merge has changed something -/// -/// Computes the join between "this" and "b" bool abstract_environmentt::merge(const abstract_environmentt &env) { // Use the sharing_map's "iterative over all differences" functionality @@ -489,22 +379,12 @@ bool abstract_environmentt::merge(const abstract_environmentt &env) } } -/// Function: abstract_environmentt::havoc -/// -/// \param havoc_string: diagnostic string to track down havoc causing. -/// -/// \return None -/// -/// 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 -/// -/// Set the domain to top void abstract_environmentt::make_top() { // since we assume anything is not in the map is top this is sufficient @@ -512,38 +392,22 @@ void abstract_environmentt::make_top() bottom = false; } -/// Function: abstract_environmentt::make_bottom -/// -/// Set the domain to top void abstract_environmentt::make_bottom() { map.clear(); bottom = true; } -/// abstract_environmentt::is_bottom -/// -/// Gets whether the domain is bottom bool abstract_environmentt::is_bottom() const { return map.empty() && bottom; } -/// Function: abstract_environmentt::is_top -/// -/// Gets whether the domain is top bool abstract_environmentt::is_top() const { return map.empty() && !bottom; } -/// Function: abstract_environmentt::output -/// -/// \param out: the stream to write to -/// \param ai: the abstract interpreter that contains this domain -/// \param ns: the current namespace -/// -/// Print out all the values in the abstract object map void abstract_environmentt::output( std::ostream &out, const ai_baset &ai, @@ -562,9 +426,6 @@ void abstract_environmentt::output( out << "}\n"; } -/// Function: abstract_environmentt::verify -/// -/// Check there aren't any null pointer mapped values bool abstract_environmentt::verify() const { decltype(map)::viewt view; @@ -601,33 +462,11 @@ abstract_object_pointert abstract_environmentt::eval_expression( return eval_obj->expression_transform(e, operands, *this, ns); } -/// Function: abstract_environmentt::erase -/// -/// \param expr: A symbol to delete from the map -/// -/// -/// Delete a symbol from the map. This is necessary if the -/// symbol falls out of scope and should no longer be tracked. void abstract_environmentt::erase(const symbol_exprt &expr) { map.erase_if_exists(expr.get_identifier()); } -/// Function: abstract_environmentt::environment_diff -/// -/// Inputs: Two abstract_environmentt's that need to be intersected for, -/// so that we can find symbols that have changed between -/// different domains. -/// -/// Outputs: An std::vector containing the symbols that are present in -/// both environments. -/// -/// Purpose: For our implementation of variable sensitivity domains, we -/// need to be able to efficiently find symbols that have changed -/// between different domains. To do this, we need to be able -/// to quickly find which symbols have new written locations, -/// which we do by finding the intersection between two different -/// domains (environments). std::vector abstract_environmentt::modified_symbols( const abstract_environmentt &first, diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 605ccbf38ec..5170b475405 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -34,14 +34,84 @@ class abstract_environmentt using map_keyt = irep_idt; abstract_environmentt(); /// These three are really the heart of the method + + /// Evaluate the value of an expression relative to the current domain + /// + /// \param expr: the expression to evaluate + /// \param ns: the current namespace + /// + /// \return The abstract_object representing the value of the expression virtual abstract_object_pointert eval(const exprt &expr, const namespacet &ns) const; + + /// Assign a value to an expression + /// + /// \param expr: the expression to assign to + /// \param value: the value to assign to the expression + /// \param ns: the namespace + /// + /// \return A boolean, true if the assignment has changed the domain. + /// + /// 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 writes (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. virtual bool assign( const exprt &expr, const abstract_object_pointert value, const namespacet &ns); + + /// Reduces the domain based on a condition + /// + /// \param expr: the expression that is to be assumed + /// \param ns: the current namespace + /// + /// \return True if the assume changed the domain. + /// + /// Reduces the domain to (an over-approximation) of the cases + /// when the the expression holds. Used to implement assume + /// statements and conditional branches. + /// It would be valid to simply return false here because it + /// is an over-approximation. We try to do better than that. + /// The better the implementation the more precise the results + /// will be. virtual bool assume(const exprt &expr, const namespacet &ns); + /// Used within assign to do the actual dispatch + /// + /// \param lhs: the abstract object for the left hand side of the write + /// (i.e. the one to update). + /// \param rhs: the value we are trying to write to the left hand side + /// \param remaining_stack: what is left of the stack before the rhs can + /// replace or be merged with the rhs + /// \param ns: the namespace + /// \param merge_write: Are we 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. + /// + /// \return A modified version of the rhs after the write has taken place + /// + /// 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 virtual abstract_object_pointert write( abstract_object_pointert lhs, abstract_object_pointert rhs, @@ -49,38 +119,98 @@ class abstract_environmentt const namespacet &ns, bool merge_write); + /// Delete a symbol from the map. This is necessary if the + /// symbol falls out of scope and should no longer be tracked. + /// + /// \param expr: A symbol to delete from the map void erase(const symbol_exprt &expr); + /// Look at the configuration for the sensitivity and create an + /// appropriate abstract_object + /// + /// \param type: the type of the object whose state should be tracked + /// \param top: does the type of the object start as top + /// \param bottom: does the type of the object start as bottom in + /// the two-value domain + /// + /// \return The abstract object that has been created virtual abstract_object_pointert abstract_object_factory( 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... + + /// For converting constants in the program + /// + /// \param type: the type of the object whose state should be tracked + /// \param expr: the starting value of the symbol + /// + /// \return The abstract object that has been created + /// + /// Look at the configuration for the sensitivity and create an + /// appropriate abstract_object, assigning an appropriate value + /// Maybe the two abstract_object_factory methods should be + /// compacted to one call... virtual abstract_object_pointert abstract_object_factory( const typet &type, const exprt &e, const namespacet &ns) const; + /// Computes the join between "this" and "b" + /// + /// \param env: the other environment + /// + /// \return A Boolean, true when the merge has changed something 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 + /// + /// \param havoc_string: diagnostic string to track down havoc causing. + /// + /// \return None + /// + /// Set the domain to top virtual void havoc(const std::string &havoc_string); + /// Set the domain to top (i.e. everything) void make_top(); + + /// Set the domain to top (i.e. no possible states / unreachable) void make_bottom(); + /// Gets whether the domain is bottom bool is_bottom() const; + + /// Gets whether the domain is top bool is_top() const; + /// Print out all the values in the abstract object map + /// + /// \param out: the stream to write to + /// \param ai: the abstract interpreter that contains this domain + /// \param ns: the current namespace void output(std::ostream &out, const class ai_baset &ai, const namespacet &ns) const; + /// Check the structural invariants are maintained. + /// In this case this is checking there aren't any null pointer mapped values bool verify() const; + /// For our implementation of variable sensitivity domains, we need + /// to be able to efficiently find symbols that have changed between + /// different domains. To do this, we need to be able to quickly + /// find which symbols have new written locations, which we do by + /// finding the intersection between two different domains + /// (environments). + /// + /// Inputs are two abstract_environmentt's that need to be + /// intersected for, so that we can find symbols that have changed + /// between different domains. + /// + /// \return An std::vector containing the symbols that are present + /// in both environments. static std::vector modified_symbols( const abstract_environmentt &first, const abstract_environmentt &second); @@ -97,6 +227,18 @@ class abstract_environmentt sharing_mapt map; private: + /// Look at the configuration for the sensitivity and create an + /// appropriate abstract_object + /// + /// \param type: the type of the object whose state should be tracked + /// \param top: does the type of the object start as top in + /// the two-value domain + /// \param bottom: does the type of the object start as bottom in + /// the two-value domain + /// \param expr: the starting value of the symbol if top and bottom + /// are both false + /// + /// \return The abstract object that has been created abstract_object_pointert abstract_object_factory( const typet &type, bool top, diff --git a/src/analyses/variable-sensitivity/abstract_object.cpp b/src/analyses/variable-sensitivity/abstract_object.cpp index 1a058e84a92..a3cfb5b04ae 100644 --- a/src/analyses/variable-sensitivity/abstract_object.cpp +++ b/src/analyses/variable-sensitivity/abstract_object.cpp @@ -22,33 +22,17 @@ #include "abstract_object.h" -/// Function: abstract_objectt::abstract_objectt -/// -/// \param type: the type the abstract_object is representing abstract_objectt::abstract_objectt(const typet &type) : t(type), bottom(false), top(true) { } -/// Function: abstract_objectt::abstract_objectt -/// -/// \param type: the type the abstract_object is representing -/// \param top: is the abstract_object starting as top -/// \param bottom: is the abstract_object starting as bottom -/// -/// 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) : t(type), bottom(bottom), top(top) { PRECONDITION(!(top && bottom)); } -/// Construct an abstract object from the expression -/// \param expr: The expression to use as the starting pointer for an abstract -/// object -/// \param environment: The environment this abstract object is being created in -/// \param ns: The namespace abstract_objectt::abstract_objectt( const exprt &expr, const abstract_environmentt &environment, @@ -57,12 +41,6 @@ abstract_objectt::abstract_objectt( { } -/// Ctor for building object of types that differ from the types of input -/// expressions -/// \param type explicitly declared type the resulting object should have -/// \param expr expression used to build the object -/// \param environment abstract environment to evaluate the expression -/// \param ns namespace to uncover names inside the expression abstract_objectt::abstract_objectt( const typet &type, const exprt &expr, @@ -72,38 +50,17 @@ abstract_objectt::abstract_objectt( { } -/// Function: abstract_objectt::type -/// -/// \return The program type this abstract object represents -/// -/// Get the real type of the variable this abstract object is representing. const typet &abstract_objectt::type() const { return t; } -/// Function: abstract_objectt::merge -/// -/// \param other: The object to merge with this -/// -/// \return Returns the result of the merge. -/// -/// 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::merge(abstract_object_pointert other) const { return abstract_object_merge(other); } -/// Function: abstract_objectt::abstract_object_merge -/// -/// \param other: The object to merge with this -/// -/// \return Returns the result of the abstract object. -/// -/// 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 { @@ -116,18 +73,6 @@ abstract_object_pointert abstract_objectt::abstract_object_merge( return merged->abstract_object_merge_internal(other); } -/** - * Helper function for abstract_objectt::abstract_object_merge to perform any - * additional actions after the base abstract_object_merge has completed it's - * actions but immediately prior to it returning. As such, this function gives - * the ability to perform additional work for a merge. - * - * This default implementation just returns itself. - * - * \param other the object to merge with this - * - * \return the result of the merge - */ abstract_object_pointert abstract_objectt::abstract_object_merge_internal( const abstract_object_pointert other) const { @@ -135,21 +80,12 @@ abstract_object_pointert abstract_objectt::abstract_object_merge_internal( return shared_from_this(); } -/// Base implementation of the meet operation: only used if no more precise -/// abstraction can be used, can only result in {TOP, BOTTOM, one of the -/// original objects} -/// \param other pointer to the abstract object to meet -/// \return the resulting abstract object pointer abstract_object_pointert abstract_objectt::meet(const abstract_object_pointert &other) const { return abstract_object_meet(other); } -/// Helper function for base meet. Two cases: return itself (if trivially -/// contained in other); return BOTTOM otherwise. -/// \param other pointer to the other object -/// \return the resulting object abstract_object_pointert abstract_objectt::abstract_object_meet( const abstract_object_pointert &other) const { @@ -162,10 +98,6 @@ abstract_object_pointert abstract_objectt::abstract_object_meet( return met->abstract_object_meet_internal(other); } -/// Helper function for base meet, in case additional work was needed. Base -/// implementation simply return pointer to itself. -/// \param other pointer to the other object -/// \return the resulting object abstract_object_pointert abstract_objectt::abstract_object_meet_internal( const abstract_object_pointert &other) const { @@ -173,16 +105,6 @@ abstract_object_pointert abstract_objectt::abstract_object_meet_internal( return shared_from_this(); } -/// Function: abstract_objectt::expression_transform -/// -/// \param expr: the expression to evaluate and find the result of it. this will -/// be the symbol referred to be op0() -/// -/// \return Returns the abstract_object representing the result of -/// this expression to the maximum precision available. -/// -/// To try and resolve different expressions with the maximum level -/// of precision available. abstract_object_pointert abstract_objectt::expression_transform( const exprt &expr, const std::vector &operands, @@ -214,18 +136,6 @@ abstract_object_pointert abstract_objectt::expression_transform( return environment.abstract_object_factory(copy.type(), copy, ns); } -/** - * A helper function to evaluate an abstract object contained - * within a container object. More precise abstractions may override this - * to return more precise results. - * - * \param env the abstract environment - * \param specifier a modifier expression, such as an array index or field - * specifier used to indicate access to a specific component - * \param ns the current namespace - * - * \return the abstract_objectt representing the value of the read component. - */ abstract_object_pointert abstract_objectt::read( const abstract_environmentt &env, const exprt &specifier, @@ -234,22 +144,6 @@ abstract_object_pointert abstract_objectt::read( return shared_from_this(); } -/** - * A helper function to evaluate writing to a component of an - * abstract object. More precise abstractions may override this to - * update what they are storing for a specific component. - * - * \param environment the abstract environment - * \param ns the current namespace - * \param stack the remaining stack of expressions on the LHS to evaluate - * \param specifier the expression uses to access a specific component - * \param value the value we are trying to write to the component - * \param merging_write if true, this and all future writes will be merged - * with the current value - * - * \return the abstract_objectt representing the result of writing - * to a specific component. - */ abstract_object_pointert abstract_objectt::write( abstract_environmentt &environment, const namespacet &ns, @@ -261,57 +155,26 @@ abstract_object_pointert abstract_objectt::write( return environment.abstract_object_factory(type(), ns, true); } -/// Function: abstract_objectt::is_top -/// -/// \return Returns true if the abstract object is representing the top (i.e. we -/// don't know anything about the value). -/// -/// Find out if the abstract object is top bool abstract_objectt::is_top() const { return top; } -/// Function: abstract_objectt::is_bottom -/// -/// \return Returns true if the abstract object is representing the bottom. -/// -/// Find out if the abstract object is bottom bool abstract_objectt::is_bottom() const { return bottom; } -/// \brief Verify the internal structure of an abstract_object is correct -/// \return true if the abstract_object is correctly constructed, or false -/// otherwise bool abstract_objectt::verify() const { return !(top && bottom); } -/// Function: abstract_objectt::to_constant -/// -/// \return Returns an exprt representing the value if the value is known and -/// constant. Otherwise returns the nil expression -/// -/// 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 -/// -/// \param out: the stream to write to -/// \param ai: the abstract interpreter that contains the abstract domain -/// (that contains the object ... ) -/// \param ns: the current namespace -/// -/// Print the value of the abstract object void abstract_objectt::output( std::ostream &out, const ai_baset &ai, @@ -331,18 +194,6 @@ void abstract_objectt::output( } } -/// Function: abstract_objectt::merge -/// -/// \param 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 -/// \param op2: the second abstract object to merge -/// -/// \return 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 -/// -/// Clones the first parameter and merges it with the second. abstract_object_pointert abstract_objectt::merge( abstract_object_pointert op1, abstract_object_pointert op2, @@ -357,27 +208,12 @@ abstract_object_pointert abstract_objectt::merge( return result; } -/// Function: abstract_objectt::should_use_base_merge -/// -/// \param other: the object being merged with -/// -/// \return Returns true if the base class is capable of doing a complete merge -/// -/// 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(); } -/// Interface method for the meet operation. Decides whether to use the base -/// implementation or if a more precise abstraction is attainable. -/// \param op1 lhs object for meet -/// \param op2 rhs object for meet -/// \param out_modifications reference to a flag indicating modification (result -/// is not op1) -/// \return resulting object after meet abstract_object_pointert abstract_objectt::meet( abstract_object_pointert op1, abstract_object_pointert op2, @@ -392,27 +228,12 @@ abstract_object_pointert abstract_objectt::meet( return result; } -/// Helper function to decide if base meet implementation should be used -/// \param other pointer to the other object to meet -/// \return true if base implementation would yield the most precise -/// abstraction anyway bool abstract_objectt::should_use_base_meet( const abstract_object_pointert &other) const { return is_bottom() || other->is_bottom() || other->is_top(); } -/** - * Update the location context for an abstract object, potentially - * propogating the update to any children of this abstract object. - * - * \param locations the set of locations to be updated - * \param update_sub_elements if true, propogate the update operation to any - * children of this abstract object - * - * \return a clone of this abstract object with it's location context - * updated - */ abstract_object_pointert abstract_objectt::update_location_context( const locationst &locations, const bool update_sub_elements) const @@ -437,13 +258,6 @@ void abstract_objectt::dump_map( out << "}"; } -/** - * \brief Dump all elements in m1 that are different or missing in m2 - * - * \param out the stream to write output to - * \param m1 the 'target' sharing_map - * \param m2 the reference sharing map - */ void abstract_objectt::dump_map_diff( std::ostream out, const abstract_objectt::shared_mapt &m1, diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 523bca8a8ad..86a9b0dd544 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -78,12 +78,36 @@ using abstract_object_visitedt = std::set; class abstract_objectt : public std::enable_shared_from_this { public: + /// \param type: the type the abstract_object is representing explicit abstract_objectt(const typet &type); + + /// Start the abstract object at either top or bottom or neither + /// Asserts if both top and bottom are true + /// + /// \param type: the type the abstract_object is representing + /// \param top: is the abstract_object starting as top + /// \param bottom: is the abstract_object starting as bottom abstract_objectt(const typet &type, bool top, bool bottom); + + /// Construct an abstract object from the expression + /// + /// \param expr: The expression to use as the starting pointer for an abstract + /// object + /// \param environment: The environment this abstract object is + /// being created in + /// \param ns: The namespace abstract_objectt( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns); + + /// Ctor for building object of types that differ from the types of input + /// expressions + /// + /// \param type explicitly declared type the resulting object should have + /// \param expr expression used to build the object + /// \param environment abstract environment to evaluate the expression + /// \param ns namespace to uncover names inside the expression abstract_objectt( const typet &type, const exprt &expr, @@ -94,9 +118,25 @@ class abstract_objectt : public std::enable_shared_from_this { } + /// Get the real type of the variable this abstract object is representing. + /// + /// \return The program type this abstract object represents const typet &type() const; + + /// Find out if the abstract object is top + /// + /// \return Returns true if the abstract object is representing the top + /// (i.e. we don't know anything about the value). virtual bool is_top() const; + + /// Find out if the abstract object is bottom + /// + /// \return Returns true if the abstract object is representing the bottom. virtual bool is_bottom() const; + + /// \brief Verify the internal structure of an abstract_object is correct + /// \return true if the abstract_object is correctly constructed, or false + /// otherwise virtual bool verify() const; virtual void get_statistics( @@ -106,19 +146,65 @@ class abstract_objectt : public std::enable_shared_from_this const namespacet &ns) const; /// Interface for transforms + /// + /// \param expr: the expression to evaluate and find the result of it. + /// This will be the symbol referred to be op0() + /// + /// \return Returns the abstract_object representing the result of + /// this expression to the maximum precision available. + /// + /// To try and resolve different expressions with the maximum level + /// of precision available. virtual abstract_object_pointert expression_transform( const exprt &expr, const std::vector &operands, const abstract_environmentt &environment, const namespacet &ns) const; + /// Converts to a constant expression if possible + /// + /// \return Returns an exprt representing the value if the value is known and + /// constant. Otherwise returns the nil expression + /// + /// 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. virtual exprt to_constant() const; + /** + * A helper function to evaluate an abstract object contained + * within a container object. More precise abstractions may override this + * to return more precise results. + * + * \param env the abstract environment + * \param specifier a modifier expression, such as an array index or field + * specifier used to indicate access to a specific component + * \param ns the current namespace + * + * \return the abstract_objectt representing the value of the read component. + */ virtual abstract_object_pointert read( const abstract_environmentt &env, const exprt &specifier, const namespacet &ns) const; + /** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ virtual abstract_object_pointert write( abstract_environmentt &environment, const namespacet &ns, @@ -127,6 +213,12 @@ class abstract_objectt : public std::enable_shared_from_this const abstract_object_pointert value, bool merging_write) const; + /// Print the value of the abstract object + /// + /// \param out: the stream to write to + /// \param ai: the abstract interpreter that contains the abstract domain + /// (that contains the object ... ) + /// \param ns: the current namespace virtual void output( std::ostream &out, const class ai_baset &ai, @@ -137,6 +229,13 @@ class abstract_objectt : public std::enable_shared_from_this shared_mapt; static void dump_map(std::ostream out, const shared_mapt &m); + /** + * \brief Dump all elements in m1 that are different or missing in m2 + * + * \param out the stream to write output to + * \param m1 the 'target' sharing_map + * \param m2 the reference sharing map + */ static void dump_map_diff(std::ostream out, const shared_mapt &m1, const shared_mapt &m2); @@ -161,19 +260,52 @@ class abstract_objectt : public std::enable_shared_from_this return this != before.get(); }; + /// Clones the first parameter and merges it with the second. + /// + /// \param 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 + /// \param op2: the second abstract object to merge + /// + /// \return 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 static abstract_object_pointert merge( abstract_object_pointert op1, abstract_object_pointert op2, bool &out_modifications); + /// Interface method for the meet operation. Decides whether to use the base + /// implementation or if a more precise abstraction is attainable. + /// \param op1 lhs object for meet + /// \param op2 rhs object for meet + /// \param out_modifications reference to a flag indicating modification + /// (result is not op1) + /// \return resulting object after meet static abstract_object_pointert meet( abstract_object_pointert op1, abstract_object_pointert op2, bool &out_modifications); + /// Base implementation of the meet operation: only used if no more precise + /// abstraction can be used, can only result in {TOP, BOTTOM, one of the + /// original objects} + /// \param other pointer to the abstract object to meet + /// \return the resulting abstract object pointer virtual abstract_object_pointert meet(const abstract_object_pointert &other) const; + /** + * Update the location context for an abstract object, potentially + * propogating the update to any children of this abstract object. + * + * \param locations the set of locations to be updated + * \param update_sub_elements if true, propogate the update operation to any + * children of this abstract object + * + * \return a clone of this abstract object with it's location context + * updated + */ virtual abstract_object_pointert update_location_context( const locationst &locations, const bool update_sub_elements) const; @@ -253,10 +385,25 @@ class abstract_objectt : public std::enable_shared_from_this { } - // Hook for a subclass to perform any additional operations as - // part of an abstract_object_merge + /** + * Helper function for abstract_objectt::abstract_object_merge to perform any + * additional actions after the base abstract_object_merge has completed it's + * actions but immediately prior to it returning. As such, this function gives + * the ability to perform additional work for a merge. + * + * This default implementation just returns itself. + * + * \param other the object to merge with this + * + * \return the result of the merge + */ virtual abstract_object_pointert abstract_object_merge_internal(const abstract_object_pointert other) const; + + /// Helper function for base meet, in case additional work was needed. Base + /// implementation simply return pointer to itself. + /// \param other pointer to the other object + /// \return the resulting object virtual abstract_object_pointert abstract_object_meet_internal(const abstract_object_pointert &other) const; @@ -273,17 +420,43 @@ class abstract_objectt : public std::enable_shared_from_this return internal_abstract_object_pointert(new abstract_objectt(*this)); } + /// Create a new abstract object that is the result of the merge, unless + /// the object would be unchanged, then would return itself. + /// + /// \param other: The object to merge with this + /// + /// \return Returns the result of the abstract object. abstract_object_pointert abstract_object_merge(const abstract_object_pointert other) const; + /// 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 + /// + /// \param other: the object being merged with + /// + /// \return Returns true if the base class is capable of doing + /// a complete merge bool should_use_base_merge(const abstract_object_pointert other) const; - // Sets the state of this object + /// Create a new abstract object that is the result of the merge, unless + /// the object would be unchanged, then would return itself. + /// + /// \param other: The object to merge with this + /// + /// \return Returns the result of the merge. virtual abstract_object_pointert merge(abstract_object_pointert other) const; + /// Helper function for base meet. Two cases: return itself (if trivially + /// contained in other); return BOTTOM otherwise. + /// \param other pointer to the other object + /// \return the resulting object abstract_object_pointert abstract_object_meet(const abstract_object_pointert &other) const; + /// Helper function to decide if base meet implementation should be used + /// \param other pointer to the other object to meet + /// \return true if base implementation would yield the most precise + /// abstraction anyway bool should_use_base_meet(const abstract_object_pointert &other) const; template diff --git a/src/analyses/variable-sensitivity/abstract_value.cpp b/src/analyses/variable-sensitivity/abstract_value.cpp index cfd952615a1..53f7c506faf 100644 --- a/src/analyses/variable-sensitivity/abstract_value.cpp +++ b/src/analyses/variable-sensitivity/abstract_value.cpp @@ -13,35 +13,15 @@ #include "abstract_value.h" -/// Function: abstract_valuet::abstract_valuet -/// -/// \param type: the type the abstract_value is representing -/// abstract_valuet::abstract_valuet(const typet &type) : abstract_objectt(type) { } -/// Function: abstract_valuet::abstract_valuet -/// -/// \param type: the type the abstract_value is representing -/// \param top: is the abstract_value starting as top -/// \param bottom: is the abstract_value starting as bottom -/// -/// 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 -/// -/// \param expr: the expression to use as the starting pointer for -/// an abstract object -/// \param environment: The environment this abstract object is being created in -/// \param ns: the namespace -/// -/// Construct an abstract value from the expression abstract_valuet::abstract_valuet( const exprt &expr, const abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/abstract_value.h b/src/analyses/variable-sensitivity/abstract_value.h index d5a54707459..9fd77214fdd 100644 --- a/src/analyses/variable-sensitivity/abstract_value.h +++ b/src/analyses/variable-sensitivity/abstract_value.h @@ -17,8 +17,24 @@ class abstract_valuet : public abstract_objectt { public: + /// \param type: the type the abstract_value is representing explicit abstract_valuet(const typet &type); + + /// Start the abstract object at either top or bottom or neither + /// Asserts if both top and bottom are true + /// + /// \param type: the type the abstract_value is representing + /// \param top: is the abstract_value starting as top + /// \param bottom: is the abstract_value starting as bottom abstract_valuet(const typet &type, bool top, bool bottom); + + /// Construct an abstract value from the expression + /// + /// \param expr: the expression to use as the starting pointer for + /// an abstract object + /// \param environment: The environment this abstract object is + /// being created in + /// \param ns: the namespace 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 29ce3c51008..b1822f54303 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/array_abstract_object.cpp @@ -11,23 +11,12 @@ #include #include -/// Function: array_abstract_objectt::array_abstract_objectt -/// -/// \param type: the type the abstract_object is representing array_abstract_objectt::array_abstract_objectt(const typet &t) : abstract_objectt(t) { PRECONDITION(t.id() == ID_array); } -/// Function: array_abstract_objectt::array_abstract_objectt -/// -/// \param type: the type the abstract_object is representing -/// \param top: is the abstract_object starting as top -/// \param bottom: is the abstract_object starting as bottom -/// -/// 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, @@ -37,12 +26,6 @@ array_abstract_objectt::array_abstract_objectt( PRECONDITION(t.id() == ID_array); } -/// Function: array_abstract_objectt::array_abstract_objectt -/// -/// \param expr: the expression to use as the starting pointer for -/// an abstract object -/// \param environment: the environment the abstract object is being created in -/// \param ns: the namespace array_abstract_objectt::array_abstract_objectt( const exprt &e, const abstract_environmentt &environment, @@ -52,18 +35,6 @@ array_abstract_objectt::array_abstract_objectt( PRECONDITION(e.type().id() == ID_array); } -/** - * A helper function to evaluate an abstract object contained - * within a container object. More precise abstractions may override this - * to return more precise results. - * - * \param env the abstract environment - * \param specifier a modifier expression, such as an array index or field - * specifier used to indicate access to a specific component - * \param ns the current namespace - * - * \return the abstract_objectt representing the value of the read component. - */ abstract_object_pointert array_abstract_objectt::read( const abstract_environmentt &env, const exprt &specifier, @@ -72,22 +43,6 @@ abstract_object_pointert array_abstract_objectt::read( return this->read_index(env, to_index_expr(specifier), ns); } -/** - * A helper function to evaluate writing to a component of an - * abstract object. More precise abstractions may override this to - * update what they are storing for a specific component. - * - * \param environment the abstract environment - * \param ns the current namespace - * \param stack the remaining stack of expressions on the LHS to evaluate - * \param specifier the expression uses to access a specific component - * \param value the value we are trying to write to the component - * \param merging_write if true, this and all future writes will be merged - * with the current value - * - * \return the abstract_objectt representing the result of writing - * to a specific component. - */ abstract_object_pointert array_abstract_objectt::write( abstract_environmentt &environment, const namespacet &ns, @@ -100,15 +55,6 @@ abstract_object_pointert array_abstract_objectt::write( environment, ns, stack, to_index_expr(specifier), value, merging_write); } -/// Function: array_abstract_objectt::read_index -/// -/// \param env: the environment -/// \param index: the expression used to access the specific value in the array -/// -/// \return An abstract object representing the value in the array -/// -/// 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, @@ -122,22 +68,6 @@ abstract_object_pointert array_abstract_objectt::read_index( return env.abstract_object_factory(subtype, ns, !is_bottom(), is_bottom()); } -/// Function: array_abstract_objectt::write_index -/// -/// \param environment: the abstract environment -/// \param ns: the namespace -/// \param stack: the remaining stack of expressions on the LHS to evaluate -/// \param index_expr: the expression uses to access a specific index -/// \param value: the value we are trying to assign to that value in the array -/// \param merging_write: ? -/// -/// \return The array_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 in the array. -/// -/// 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 namespacet &ns, diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index 44a23a355dc..652de1866a8 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -21,18 +21,60 @@ class index_exprt; class array_abstract_objectt : public abstract_objectt { public: + /// \param type: the type the abstract_object is representing explicit array_abstract_objectt(const typet &type); + + /// Start the abstract object at either top or bottom or neither + /// Asserts if both top and bottom are true + /// + /// \param type: the type the abstract_object is representing + /// \param top: is the abstract_object starting as top + /// \param bottom: is the abstract_object starting as bottom array_abstract_objectt(const typet &type, bool top, bool bottom); + + /// \param expr: the expression to use as the starting pointer for + /// an abstract object + /// \param environment: the environment the abstract object is + /// being created in + /// \param ns: the namespace explicit array_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns); + /** + * A helper function to evaluate an abstract object contained + * within a container object. More precise abstractions may override this + * to return more precise results. + * + * \param env the abstract environment + * \param specifier a modifier expression, such as an array index or field + * specifier used to indicate access to a specific component + * \param ns the current namespace + * + * \return the abstract_objectt representing the value of the read component. + */ abstract_object_pointert read( const abstract_environmentt &env, const exprt &specifier, const namespacet &ns) const override; + /** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ abstract_object_pointert write( abstract_environmentt &environment, const namespacet &ns, @@ -50,11 +92,33 @@ class array_abstract_objectt : public abstract_objectt protected: CLONE + /// A helper function to read elements from an array. More precise + /// abstractions may override this to provide more precise results. + /// + /// \param env: the environment + /// \param index: the expression used to access the specific value + /// in the array + /// + /// \return An abstract object representing the value in the array virtual abstract_object_pointert read_index( const abstract_environmentt &env, const index_exprt &index, const namespacet &ns) const; + /// 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. + /// + /// \param environment: the abstract environment + /// \param ns: the namespace + /// \param stack: the remaining stack of expressions on the LHS to evaluate + /// \param index_expr: the expression uses to access a specific index + /// \param value: the value we are trying to assign to that value in the array + /// \param merging_write: ? + /// + /// \return The array_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 in the array. virtual sharing_ptrt write_index( abstract_environmentt &environment, const namespacet &ns, diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.cpp b/src/analyses/variable-sensitivity/constant_abstract_value.cpp index 5f208852783..58af0459797 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.cpp +++ b/src/analyses/variable-sensitivity/constant_abstract_value.cpp @@ -170,14 +170,6 @@ void constant_abstract_valuet::output( } } -/// Function: constant_abstract_valuet::merge -/// -/// \param other: the abstract object to merge with -/// -/// \return Returns the result of the merge -/// -/// Attempts to do a constant/constant merge if both are constants, -/// otherwise falls back to the parent merge abstract_object_pointert constant_abstract_valuet::merge(abstract_object_pointert other) const { @@ -194,15 +186,6 @@ constant_abstract_valuet::merge(abstract_object_pointert other) const } } -/// Function: constant_abstract_valuet::merge_constant_constant -/// -/// \param other: the abstract object to merge with -/// -/// \return 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. -/// -/// Merges another constant abstract value into this one abstract_object_pointert constant_abstract_valuet::merge_constant_constant( constant_abstract_value_pointert other) const { diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index c588ed17613..0c62d4ab16b 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -68,6 +68,13 @@ class constant_abstract_valuet : public abstract_valuet protected: CLONE + + /// Attempts to do a constant/constant merge if both are constants, + /// otherwise falls back to the parent merge + /// + /// \param other: the abstract object to merge with + /// + /// \return Returns the result of the merge abstract_object_pointert merge(abstract_object_pointert other) const override; abstract_object_pointert try_transform_expr_with_all_rounding_modes( @@ -76,6 +83,13 @@ class constant_abstract_valuet : public abstract_valuet const namespacet &ns) const; private: + /// Merges another constant abstract value into this one + /// + /// \param other: the abstract object to merge with + /// + /// \return 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. abstract_object_pointert merge_constant_constant(constant_abstract_value_pointert other) const; diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp index 7e5cf2bc148..f1e19585b88 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.cpp @@ -14,23 +14,12 @@ #include "constant_array_abstract_object.h" -/// Function: constant_array_abstract_objectt::constant_array_abstract_objectt -/// -/// \param type: the type the abstract_object is representing constant_array_abstract_objectt::constant_array_abstract_objectt(typet type) : array_abstract_objectt(type) { DATA_INVARIANT(verify(), "Structural invariants maintained"); } -/// Function: constant_array_abstract_objectt::constant_array_abstract_objectt -/// -/// \param type: the type the abstract_object is representing -/// \param top: is the abstract_object starting as top -/// \param bottom: is the abstract_object starting as bottom -/// -/// 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, @@ -40,12 +29,6 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( DATA_INVARIANT(verify(), "Structural invariants maintained"); } -/// Function: constant_array_abstract_objectt::constant_array_abstract_objectt -/// -/// \param expr: the expression to use as the starting pointer for -/// an abstract object -/// \param environment: the environment the abstract object is being created in -/// \param ns: the namespace constant_array_abstract_objectt::constant_array_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, @@ -65,14 +48,6 @@ constant_array_abstract_objectt::constant_array_abstract_objectt( DATA_INVARIANT(verify(), "Structural invariants maintained"); } -/// Function: constant_array_abstract_objectt::verify -/// -/// \return Returns true if the struct is valid -/// -/// 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 constant_array_abstract_objectt::verify() const { // Either the object is top or bottom (=> map empty) @@ -81,8 +56,6 @@ bool constant_array_abstract_objectt::verify() const (is_top() || is_bottom()) == map.empty(); } -/// \brief Perform any additional structural modifications when setting this -/// object to TOP void constant_array_abstract_objectt::make_top_internal() { // A structural invariant of constant_array_abstract_objectt is that @@ -90,14 +63,6 @@ void constant_array_abstract_objectt::make_top_internal() map.clear(); } -/// Function: constant_array_abstract_objectt::merge -/// -/// \param other: The object to merge in -/// -/// \return Returns the result of the merge. -/// -/// Tries to do an array/array merge if merging with a constant array -/// If it can't, falls back to parent merge abstract_object_pointert constant_array_abstract_objectt::merge(abstract_object_pointert other) const { @@ -114,15 +79,6 @@ constant_array_abstract_objectt::merge(abstract_object_pointert other) const } } -/// Function: constant_array_abstract_objectt::constant_array_merge -/// -/// \param other: The object to merge in -/// -/// \return 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.. -/// -/// Merges an array into this array abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( const constant_array_pointert other) const { @@ -155,16 +111,6 @@ abstract_object_pointert constant_array_abstract_objectt::constant_array_merge( } } -/// Function: constant_array_abstract_objectt::output -/// -/// \param out: the stream to write to -/// \param ai: the abstract interpreter that contains the abstract domain -/// (that contains the object ... ) -/// \param ns: the current namespace -/// -/// 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, @@ -394,15 +316,6 @@ constant_array_abstract_objectt::write_index( } } -/// Function: constant_array_abstract_objectt::get_top_entry -/// -/// \param environment: the abstract environment -/// \param ns: the namespace -/// -/// \return 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 @@ -410,15 +323,6 @@ abstract_object_pointert constant_array_abstract_objectt::get_top_entry( return env.abstract_object_factory(type().subtype(), ns, true, false); } -/// Function: constant_array_abstract_objectt::eval_index -/// -/// \param environment: the abstract environment -/// \param ns: the namespace -/// -/// \return An abstract object pointer of type type().subtype() (i.e. the -/// type of the array's values). -/// -/// 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, @@ -439,17 +343,6 @@ bool constant_array_abstract_objectt::eval_index( } } -/** - * Apply a visitor operation to all sub elements of this abstract_object. - * A sub element might be a member of a struct, or an element of an array, - * for instance, but this is entirely determined by the particular - * derived instance of abstract_objectt. - * - * \param visitor an instance of a visitor class that will be applied to - * all sub elements - * \return A new abstract_object if it's contents is modifed, or this if - * no modification is needed - */ abstract_object_pointert constant_array_abstract_objectt::visit_sub_elements( const abstract_object_visitort &visitor) const { diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index ffefe29fc2c..0bd46d66c71 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -27,8 +27,22 @@ class constant_array_abstract_objectt : public array_abstract_objectt typedef sharing_ptrt const constant_array_pointert; + /// \param type: the type the abstract_object is representing explicit constant_array_abstract_objectt(typet type); + + /// Start the abstract object at either top or bottom or neither + /// Asserts if both top and bottom are true + /// + /// \param type: the type the abstract_object is representing + /// \param top: is the abstract_object starting as top + /// \param bottom: is the abstract_object starting as bottom constant_array_abstract_objectt(typet type, bool top, bool bottom); + + /// \param expr: the expression to use as the starting pointer for + /// an abstract object + /// \param environment: the environment the abstract object is + /// being created in + /// \param ns: the namespace constant_array_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, @@ -38,9 +52,27 @@ class constant_array_abstract_objectt : public array_abstract_objectt { } + /// the current known value about this object. For this array we + /// print: { [0] - write_index( abstract_environmentt &environment, const namespacet &ns, @@ -66,11 +119,33 @@ class constant_array_abstract_objectt : public array_abstract_objectt const abstract_object_pointert value, bool merging_write) const override; + /// Tries to do an array/array merge if merging with a constant array + /// If it can't, falls back to parent merge + /// + /// \param other: The object to merge in + /// + /// \return Returns the result of the merge. abstract_object_pointert merge(abstract_object_pointert other) const override; + /// 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 + /// + /// \return Returns true if the struct is valid bool verify() const override; + + /// \brief Perform any additional structural modifications when setting this + /// object to TOP void make_top_internal() override; + /// Short hand method for creating a top element of the array + /// + /// \param environment: the abstract environment + /// \param ns: the namespace + /// + /// \return An abstract object pointer of type type().subtype() (i.e. the + /// type of the array's values). virtual bool eval_index( const index_exprt &index, const abstract_environmentt &env, @@ -98,9 +173,24 @@ class constant_array_abstract_objectt : public array_abstract_objectt shared_array_mapt map; + /// Short hand method for creating a top element of the array + /// + /// \param environment: the abstract environment + /// \param ns: the namespace + /// + /// \return An abstract object pointer of type type().subtype() (i.e. the + /// type of the array's values). + /// abstract_object_pointert get_top_entry(const abstract_environmentt &env, const namespacet &ns) const; + /// Merges an array into this array + /// + /// \param other: The object to merge in + /// + /// \return 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.. abstract_object_pointert constant_array_merge(const constant_array_pointert other) const; }; diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 30e8a8b6675..20c2cae60bd 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -20,20 +20,12 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com # include #endif -/** - * \brief Explicit copy-constructor to make it clear that the shared_map - * used to store the values of fields is copy-constructed as well - * to ensure it shares as much data as possible. - */ full_struct_abstract_objectt::full_struct_abstract_objectt( const full_struct_abstract_objectt &ao) : struct_abstract_objectt(ao), map(ao.map) { } -/// Function: full_struct_abstract_objectt::struct_abstract_objectt -/// -/// \param type: the type the abstract_object is representing full_struct_abstract_objectt::full_struct_abstract_objectt(const typet &t) : struct_abstract_objectt(t) { @@ -41,14 +33,6 @@ full_struct_abstract_objectt::full_struct_abstract_objectt(const typet &t) DATA_INVARIANT(verify(), "Structural invariants maintained"); } -/// Function: struct_abstract_objectt::struct_abstract_objectt -/// -/// \param type: the type the abstract_object is representing -/// \param top: is the abstract_object starting as top -/// \param bottom: is the abstract_object starting as bottom -/// -/// 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, @@ -59,10 +43,6 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( DATA_INVARIANT(verify(), "Structural invariants maintained"); } -/// Function: full_struct_abstract_objectt::full_struct_abstract_objectt -/// -/// \param expr: the expression to use as the starting pointer for an -/// abstract object full_struct_abstract_objectt::full_struct_abstract_objectt( const exprt &e, const abstract_environmentt &environment, @@ -92,18 +72,6 @@ full_struct_abstract_objectt::full_struct_abstract_objectt( DATA_INVARIANT(verify(), "Structural invariants maintained"); } -/// Function: struct_abstract_objectt::read_component -/// -/// \param environment: the abstract environment -/// \param member_expr: the expression uses to access a specific component -/// -/// \return The abstract object representing the value of that -/// component. For this abstraction this will always be top -/// since we are not tracking the struct. -/// -/// 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, @@ -136,21 +104,6 @@ abstract_object_pointert full_struct_abstract_objectt::read_component( } } -/// Function: struct_abstract_objectt::write_component -/// -/// \param environment: the abstract environment -/// \param stack: the remaining stack of expressions on the LHS to evaluate -/// \param member_expr: the expression uses to access a specific component -/// \param value: the value we are trying to write to the component -/// -/// \return 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. -/// -/// 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, @@ -247,16 +200,6 @@ full_struct_abstract_objectt::write_component( } } -/// Function: full_struct_abstract_objectt::output -/// -/// \param out: the stream to write to -/// \param ai: the abstract interpreter that contains the abstract domain -/// (that contains the object ... ) -/// \param ns: the current namespace -/// -/// To provide a human readable string to the out representing -/// the current known value about this object. For this array we -/// print: { .component_name= map empty) @@ -303,15 +238,6 @@ bool full_struct_abstract_objectt::verify() const return (is_top() || is_bottom()) == map.empty(); } -/// Function: full_struct_abstract_objectt::merge -/// -/// \param other: the other object being merged -/// -/// \return Returns the result of the merge. -/// -/// 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. abstract_object_pointert full_struct_abstract_objectt::merge(abstract_object_pointert other) const { @@ -328,15 +254,6 @@ full_struct_abstract_objectt::merge(abstract_object_pointert other) const } } -/// Function: full_struct_abstract_objectt::merge_constant_structs -/// -/// \param other: the other object being merged -/// -/// \return 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. -/// -/// Performs an element wise merge of the map for each struct abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( constant_struct_pointert other) const { @@ -367,17 +284,6 @@ abstract_object_pointert full_struct_abstract_objectt::merge_constant_structs( } } -/** - * Apply a visitor operation to all sub elements of this abstract_object. - * A sub element might be a member of a struct, or an element of an array, - * for instance, but this is entirely determined by the particular - * derived instance of abstract_objectt. - * - * \param visitor an instance of a visitor class that will be applied to - * all sub elements - * \return A new abstract_object if it's contents is modifed, or this if - * no modification is needed - */ abstract_object_pointert full_struct_abstract_objectt::visit_sub_elements( const abstract_object_visitort &visitor) const { diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 56e67f10b86..4bccc23a1ff 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -25,23 +25,55 @@ class full_struct_abstract_objectt : public struct_abstract_objectt public: typedef sharing_ptrt constant_struct_pointert; - // Define an explicit copy constructor to ensure sharing of maps + /** + * \brief Explicit copy-constructor to make it clear that the shared_map + * used to store the values of fields is copy-constructed as well + * to ensure it shares as much data as possible. + */ full_struct_abstract_objectt(const full_struct_abstract_objectt &ao); + /// \param type: the type the abstract_object is representing explicit full_struct_abstract_objectt(const typet &type); + /// Start the abstract object at either top or bottom or + /// neither asserts if both top and bottom are true + /// + /// \param type: the type the abstract_object is representing + /// \param top: is the abstract_object starting as top + /// \param bottom: is the abstract_object starting as bottom full_struct_abstract_objectt(const typet &type, bool top, bool bottom); + /// \param expr: the expression to use as the starting pointer for an + /// abstract object full_struct_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns); + /// To provide a human readable string to the out representing + /// the current known value about this object. For this array we + /// print: { .component_name= write_component( abstract_environmentt &environment, const namespacet &ns, @@ -77,9 +138,23 @@ class full_struct_abstract_objectt : public struct_abstract_objectt const abstract_object_pointert value, bool merging_write) const override; + /// Function: full_struct_abstract_objectt::verify + /// + /// \return Returns true if the struct is valid + /// + /// 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 verify() const override; - // Set the state of this to the merge result of op1 and op2 and - // return if the result is different from op1 + + /// 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. + /// + /// \param other: the other object being merged + /// + /// \return Returns the result of the merge. abstract_object_pointert merge(abstract_object_pointert other) const override; }; diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index 8b694518cb8..d68a48d3e29 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -12,23 +12,12 @@ #include "pointer_abstract_object.h" -/// Function: pointer_abstract_objectt::pointer_abstract_objectt -/// -/// \param type: the type the abstract_object is representing pointer_abstract_objectt::pointer_abstract_objectt(const typet &t) : abstract_objectt(t) { PRECONDITION(t.id() == ID_pointer); } -/// Function: pointer_abstract_objectt::pointer_abstract_objectt -/// -/// \param type: the type the abstract_object is representing -/// \param top: is the abstract_object starting as top -/// \param bottom: is the abstract_object starting as bottom -/// -/// 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, @@ -38,10 +27,6 @@ pointer_abstract_objectt::pointer_abstract_objectt( PRECONDITION(t.id() == ID_pointer); } -/// Function: pointer_abstract_objectt::pointer_abstract_objectt -/// -/// \param expr: the expression to use as the starting pointer for -/// an abstract object pointer_abstract_objectt::pointer_abstract_objectt( const exprt &e, const abstract_environmentt &environment, @@ -51,18 +36,6 @@ pointer_abstract_objectt::pointer_abstract_objectt( PRECONDITION(e.type().id() == ID_pointer); } -/** - * A helper function to evaluate an abstract object contained - * within a container object. More precise abstractions may override this - * to return more precise results. - * - * \param env the abstract environment - * \param specifier a modifier expression, such as an array index or field - * specifier used to indicate access to a specific component - * \param ns the current namespace - * - * \return the abstract_objectt representing the value of the read component. - */ abstract_object_pointert pointer_abstract_objectt::read( const abstract_environmentt &env, const exprt &specifier, @@ -71,22 +44,6 @@ abstract_object_pointert pointer_abstract_objectt::read( return read_dereference(env, ns); } -/** - * A helper function to evaluate writing to a component of an - * abstract object. More precise abstractions may override this to - * update what they are storing for a specific component. - * - * \param environment the abstract environment - * \param ns the current namespace - * \param stack the remaining stack of expressions on the LHS to evaluate - * \param specifier the expression uses to access a specific component - * \param value the value we are trying to write to the component - * \param merging_write if true, this and all future writes will be merged - * with the current value - * - * \return the abstract_objectt representing the result of writing - * to a specific component. - */ abstract_object_pointert pointer_abstract_objectt::write( abstract_environmentt &environment, const namespacet &ns, @@ -98,15 +55,6 @@ abstract_object_pointert pointer_abstract_objectt::write( return write_dereference(environment, ns, stack, value, merging_write); } -/// Function: pointer_abstract_objectt::read_dereference -/// -/// \param env: the environment -/// \param ns: the namespace -/// -/// \return An abstract object representing the value being pointed to -/// -/// 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 namespacet &ns) const @@ -117,24 +65,6 @@ abstract_object_pointert pointer_abstract_objectt::read_dereference( return env.abstract_object_factory(pointed_to_type, ns, true, false); } -/// Function: pointer_abstract_objectt::write_dereference -/// -/// \param environment: the abstract environment -/// \param ns: the namespace -/// \param stack: the remaining stack of expressions on the LHS to evaluate -/// \param value: the value we are trying to assign to what the pointer is -/// pointing to -/// \param 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 -/// -/// \return A modified abstract object representing this pointer after it -/// has been written to. -/// -/// 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, diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index db2ae8cf120..656f38bb657 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -21,18 +21,57 @@ class abstract_environmentt; class pointer_abstract_objectt : public abstract_objectt { public: + /// \param type: the type the abstract_object is representing explicit pointer_abstract_objectt(const typet &type); + + /// Start the abstract object at either top or bottom or neither + /// Asserts if both top and bottom are true + /// + /// \param type: the type the abstract_object is representing + /// \param top: is the abstract_object starting as top + /// \param bottom: is the abstract_object starting as bottom pointer_abstract_objectt(const typet &type, bool top, bool bottom); + + /// \param expr: the expression to use as the starting pointer for + /// an abstract object explicit pointer_abstract_objectt( const exprt &e, const abstract_environmentt &environment, const namespacet &ns); + /** + * A helper function to evaluate an abstract object contained + * within a container object. More precise abstractions may override this + * to return more precise results. + * + * \param env the abstract environment + * \param specifier a modifier expression, such as an array index or field + * specifier used to indicate access to a specific component + * \param ns the current namespace + * + * \return the abstract_objectt representing the value of the read component. + */ abstract_object_pointert read( const abstract_environmentt &env, const exprt &specifier, const namespacet &ns) const override; + /** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ abstract_object_pointert write( abstract_environmentt &environment, const namespacet &ns, @@ -50,11 +89,33 @@ class pointer_abstract_objectt : public abstract_objectt protected: CLONE - // pointer interface + /// A helper function to read elements from an array. More precise + /// abstractions may override this to provide more precise results. + /// + /// \param env: the environment + /// \param ns: the namespace + /// + /// \return An abstract object representing the value being pointed to virtual abstract_object_pointert read_dereference( const abstract_environmentt &env, const namespacet &ns) const; + /// A helper function to evaluate writing to a pointers value. More + /// precise abstractions may override this provide more precise results. + /// + /// \param environment: the abstract environment + /// \param ns: the namespace + /// \param stack: the remaining stack of expressions on the LHS to evaluate + /// \param value: the value we are trying to assign to what the pointer is + /// pointing to + /// \param 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 + /// + /// \return A modified abstract object representing this pointer after it + /// has been written to. virtual sharing_ptrt write_dereference( abstract_environmentt &environment, const namespacet &ns, diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.cpp b/src/analyses/variable-sensitivity/struct_abstract_object.cpp index 3ae827b4f32..174a69c699d 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/struct_abstract_object.cpp @@ -13,23 +13,12 @@ #include "struct_abstract_object.h" -/// Function: struct_abstract_objectt::struct_abstract_objectt -/// -/// \param type: the type the abstract_object is representing struct_abstract_objectt::struct_abstract_objectt(const typet &t) : abstract_objectt(t) { PRECONDITION(t.id() == ID_struct); } -/// Function: struct_abstract_objectt::struct_abstract_objectt -/// -/// \param type: the type the abstract_object is representing -/// \param top: is the abstract_object starting as top -/// \param bottom: is the abstract_object starting as bottom -/// -/// \return 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, @@ -39,10 +28,6 @@ struct_abstract_objectt::struct_abstract_objectt( PRECONDITION(t.id() == ID_struct); } -/// Function: struct_abstract_objectt::struct_abstract_objectt -/// -/// \param expr: the expression to use as the starting pointer for -/// an abstract object struct_abstract_objectt::struct_abstract_objectt( const exprt &e, const abstract_environmentt &environment, @@ -52,18 +37,6 @@ struct_abstract_objectt::struct_abstract_objectt( PRECONDITION(ns.follow(e.type()).id() == ID_struct); } -/** - * A helper function to evaluate an abstract object contained - * within a container object. More precise abstractions may override this - * to return more precise results. - * - * \param env the abstract environment - * \param specifier a modifier expression, such as an array index or field - * specifier used to indicate access to a specific component - * \param ns the current namespace - * - * \return the abstract_objectt representing the value of the read component. - */ abstract_object_pointert struct_abstract_objectt::read( const abstract_environmentt &env, const exprt &specifier, @@ -72,22 +45,6 @@ abstract_object_pointert struct_abstract_objectt::read( return this->read_component(env, to_member_expr(specifier), ns); } -/** - * A helper function to evaluate writing to a component of an - * abstract object. More precise abstractions may override this to - * update what they are storing for a specific component. - * - * \param environment the abstract environment - * \param ns the current namespace - * \param stack the remaining stack of expressions on the LHS to evaluate - * \param specifier the expression uses to access a specific component - * \param value the value we are trying to write to the component - * \param merging_write if true, this and all future writes will be merged - * with the current value - * - * \return the abstract_objectt representing the result of writing - * to a specific component. - */ abstract_object_pointert struct_abstract_objectt::write( abstract_environmentt &environment, const namespacet &ns, @@ -100,18 +57,6 @@ abstract_object_pointert struct_abstract_objectt::write( environment, ns, stack, to_member_expr(specifier), value, merging_write); } -/// Function: struct_abstract_objectt::read_component -/// -/// \param environment: the abstract environment -/// \param member_expr: the expression uses to access a specific component -/// -/// \return The abstract object representing the value of that component. For -/// this abstraction this will always be top since we are not tracking -/// the struct. -/// -/// 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, @@ -123,20 +68,6 @@ abstract_object_pointert struct_abstract_objectt::read_component( member_expr.type(), ns, !is_bottom(), is_bottom()); } -/// Function: struct_abstract_objectt::write_component -/// -/// \param environment: the abstract environment -/// \param stack: the remaining stack of expressions on the LHS to evaluate -/// \param member_expr: the expression uses to access a specific component -/// \param value: the value we are trying to write to the component -/// -/// \return 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. -/// -/// 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( abstract_environmentt &environment, const namespacet &ns, diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index 88fc3c76a1d..0a3029c5f18 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -21,18 +21,57 @@ class member_exprt; class struct_abstract_objectt : public abstract_objectt { public: + /// \param type: the type the abstract_object is representing explicit struct_abstract_objectt(const typet &type); + + /// \param type: the type the abstract_object is representing + /// \param top: is the abstract_object starting as top + /// \param bottom: is the abstract_object starting as bottom + /// + /// \return Start the abstract object at either top or bottom or neither + /// Asserts if both top and bottom are true struct_abstract_objectt(const typet &type, bool top, bool bottom); + + /// \param expr: the expression to use as the starting pointer for + /// an abstract object explicit struct_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns); + /** + * A helper function to evaluate an abstract object contained + * within a container object. More precise abstractions may override this + * to return more precise results. + * + * \param env the abstract environment + * \param specifier a modifier expression, such as an array index or field + * specifier used to indicate access to a specific component + * \param ns the current namespace + * + * \return the abstract_objectt representing the value of the read component. + */ abstract_object_pointert read( const abstract_environmentt &env, const exprt &specifier, const namespacet &ns) const override; + /** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ abstract_object_pointert write( abstract_environmentt &environment, const namespacet &ns, @@ -50,12 +89,34 @@ class struct_abstract_objectt : public abstract_objectt protected: CLONE - // struct interface + /// A helper function to evaluate the abstract object contained + /// within a struct. More precise abstractions may override this + /// to return more precise results. + /// + /// \param environment: the abstract environment + /// \param member_expr: the expression uses to access a specific component + /// + /// \return The abstract object representing the value of that component. For + /// this abstraction this will always be top since we are not tracking + /// the struct. + /// virtual abstract_object_pointert read_component( const abstract_environmentt &environment, const member_exprt &member_expr, const namespacet &ns) const; + /// 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. + /// + /// \param environment: the abstract environment + /// \param stack: the remaining stack of expressions on the LHS to evaluate + /// \param member_expr: the expression uses to access a specific component + /// \param value: the value we are trying to write to the component + /// + /// \return 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. virtual sharing_ptrt write_component( abstract_environmentt &environment, const namespacet &ns, diff --git a/src/analyses/variable-sensitivity/union_abstract_object.cpp b/src/analyses/variable-sensitivity/union_abstract_object.cpp index 215d8442ad3..f4e4e902190 100644 --- a/src/analyses/variable-sensitivity/union_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/union_abstract_object.cpp @@ -12,23 +12,12 @@ #include "union_abstract_object.h" -/// Function: union_abstract_objectt::union_abstract_objectt -/// -/// \param type: the type the abstract_object is representing union_abstract_objectt::union_abstract_objectt(const typet &type) : abstract_objectt(type) { PRECONDITION(type.id() == ID_union); } -/// Function: union_abstract_objectt::union_abstract_objectt -/// -/// \param type: the type the abstract_object is representing -/// \param top: is the abstract_object starting as top -/// \param bottom: is the abstract_object starting as bottom -/// -/// Start the abstract object at either top or bottom or neither -/// Asserts if both top and bottom are true union_abstract_objectt::union_abstract_objectt( const typet &type, bool top, @@ -38,12 +27,6 @@ union_abstract_objectt::union_abstract_objectt( PRECONDITION(type.id() == ID_union); } -/// Function: union_abstract_objectt::union_abstract_objectt -/// -/// \param expr: the expression to use as the starting pointer for -/// an abstract object -/// \param environment: the environment the abstract object is going -/// to be evaluated in. union_abstract_objectt::union_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, @@ -53,18 +36,6 @@ union_abstract_objectt::union_abstract_objectt( PRECONDITION(ns.follow(expr.type()).id() == ID_union); } -/** - * A helper function to evaluate an abstract object contained - * within a container object. More precise abstractions may override this - * to return more precise results. - * - * \param env the abstract environment - * \param specifier a modifier expression, such as an array index or field - * specifier used to indicate access to a specific component - * \param ns the current namespace - * - * \return the abstract_objectt representing the value of the read component. - */ abstract_object_pointert union_abstract_objectt::read( const abstract_environmentt &env, const exprt &specifier, @@ -73,22 +44,6 @@ abstract_object_pointert union_abstract_objectt::read( return read_component(env, to_member_expr(specifier), ns); } -/** - * A helper function to evaluate writing to a component of an - * abstract object. More precise abstractions may override this to - * update what they are storing for a specific component. - * - * \param environment the abstract environment - * \param ns the current namespace - * \param stack the remaining stack of expressions on the LHS to evaluate - * \param specifier the expression uses to access a specific component - * \param value the value we are trying to write to the component - * \param merging_write if true, this and all future writes will be merged - * with the current value - * - * \return the abstract_objectt representing the result of writing - * to a specific component. - */ abstract_object_pointert union_abstract_objectt::write( abstract_environmentt &environment, const namespacet &ns, @@ -101,18 +56,6 @@ abstract_object_pointert union_abstract_objectt::write( environment, ns, stack, to_member_expr(specifier), value, merging_write); } -/// Function: union_abstract_objectt::read_component -/// -/// \param environment: the abstract environment -/// \param member_expr: the expression uses to access a specific component -/// -/// The abstract object representing the value of that component. For -/// this abstraction this will always be top since we are not tracking -/// the union. -/// -/// A helper function to evaluate the abstract object contained -/// within a union. More precise abstractions may override this -/// to return more precise results. abstract_object_pointert union_abstract_objectt::read_component( const abstract_environmentt &environment, const member_exprt &member_expr, @@ -122,20 +65,6 @@ abstract_object_pointert union_abstract_objectt::read_component( member_expr.type(), ns, !is_bottom(), is_bottom()); } -/// Function: union_abstract_objectt::write_component -/// -/// \param environment: the abstract environment -/// \param stack: the remaining stack of expressions on the LHS to evaluate -/// \param member_expr: the expression uses to access a specific component -/// \param value: the value we are trying to write to the component -/// -/// \return The union_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 union. -/// -/// A helper function to evaluate writing to a component of a union. -/// More precise abstractions may override this to -/// update what they are storing for a specific component. sharing_ptrt union_abstract_objectt::write_component( abstract_environmentt &environment, const namespacet &ns, diff --git a/src/analyses/variable-sensitivity/union_abstract_object.h b/src/analyses/variable-sensitivity/union_abstract_object.h index e7109c97592..c20a0fc2147 100644 --- a/src/analyses/variable-sensitivity/union_abstract_object.h +++ b/src/analyses/variable-sensitivity/union_abstract_object.h @@ -21,18 +21,59 @@ class member_exprt; class union_abstract_objectt : public abstract_objectt { public: + /// \param type: the type the abstract_object is representing explicit union_abstract_objectt(const typet &type); + + /// Start the abstract object at either top or bottom or neither + /// Asserts if both top and bottom are true + /// + /// \param type: the type the abstract_object is representing + /// \param top: is the abstract_object starting as top + /// \param bottom: is the abstract_object starting as bottom union_abstract_objectt(const typet &type, bool top, bool bottom); + + /// \param expr: the expression to use as the starting pointer for + /// an abstract object + /// \param environment: the environment the abstract object is going + /// to be evaluated in. explicit union_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns); + /** + * A helper function to evaluate an abstract object contained + * within a container object. More precise abstractions may override this + * to return more precise results. + * + * \param env the abstract environment + * \param specifier a modifier expression, such as an array index or field + * specifier used to indicate access to a specific component + * \param ns the current namespace + * + * \return the abstract_objectt representing the value of the read component. + */ abstract_object_pointert read( const abstract_environmentt &env, const exprt &specifier, const namespacet &ns) const override; + /** + * A helper function to evaluate writing to a component of an + * abstract object. More precise abstractions may override this to + * update what they are storing for a specific component. + * + * \param environment the abstract environment + * \param ns the current namespace + * \param stack the remaining stack of expressions on the LHS to evaluate + * \param specifier the expression uses to access a specific component + * \param value the value we are trying to write to the component + * \param merging_write if true, this and all future writes will be merged + * with the current value + * + * \return the abstract_objectt representing the result of writing + * to a specific component. + */ abstract_object_pointert write( abstract_environmentt &environment, const namespacet &ns, @@ -44,12 +85,33 @@ class union_abstract_objectt : public abstract_objectt protected: CLONE - // union interface + /// A helper function to evaluate the abstract object contained + /// within a union. More precise abstractions may override this + /// to return more precise results. + /// + /// \param environment: the abstract environment + /// \param member_expr: the expression uses to access a specific component + /// + /// The abstract object representing the value of that component. For + /// this abstraction this will always be top since we are not tracking + /// the union. virtual abstract_object_pointert read_component( const abstract_environmentt &environment, const member_exprt &member_expr, const namespacet &ns) const; + /// A helper function to evaluate writing to a component of a union. + /// More precise abstractions may override this to + /// update what they are storing for a specific component. + /// + /// \param environment: the abstract environment + /// \param stack: the remaining stack of expressions on the LHS to evaluate + /// \param member_expr: the expression uses to access a specific component + /// \param value: the value we are trying to write to the component + /// + /// \return The union_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 union. virtual sharing_ptrt write_component( abstract_environmentt &environment, const namespacet &ns, diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 31be5babf7f..6adad231d64 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -21,16 +21,6 @@ Date: April 2016 # include #endif -/// Function: variable_sensitivity_domaint::transform -/// -/// \param from: the instruction before the abstract domain -/// \param to: the instruction after the abstract domain -/// \param ai: the abstract interpreter -/// \param ns: the namespace -/// -/// \return none -/// -/// Compute the abstract transformer for a single instruction void variable_sensitivity_domaint::transform( const irep_idt &function_from, locationt from, @@ -185,15 +175,6 @@ void variable_sensitivity_domaint::transform( DATA_INVARIANT(abstract_state.verify(), "Structural invariant"); } -/// Function: variable_sensitivity_domaint::output -/// -/// \param out: the output stream -/// \param ai: the abstract interpreter -/// \param ns: the namespace -/// -/// \return none -/// -/// Basic text output of the abstract domain void variable_sensitivity_domaint::output( std::ostream &out, const ai_baset &ai, @@ -202,40 +183,22 @@ void variable_sensitivity_domaint::output( abstract_state.output(out, ai, ns); } -/// Function: variable_sensitivity_domaint::make_bottom -/// -/// Sets the domain to bottom (no relations). void variable_sensitivity_domaint::make_bottom() { abstract_state.make_bottom(); return; } -/// Function: variable_sensitivity_domaint::make_top -/// -/// Sets the domain to top (all relations). void variable_sensitivity_domaint::make_top() { abstract_state.make_top(); } -/// Function: variable_sensitivity_domaint::make_entry -/// -/// Set up a sane entry state. void variable_sensitivity_domaint::make_entry() { abstract_state.make_top(); } -/// Function: variable_sensitivity_domaint::merge -/// -/// \param b: the other domain -/// \param from: it's preceding location -/// \param to: it's current location -/// -/// \return true if something has changed. -/// -/// Computes the join between "this" and "b". bool variable_sensitivity_domaint::merge( const variable_sensitivity_domaint &b, locationt from, @@ -253,17 +216,6 @@ bool variable_sensitivity_domaint::merge( return any_changes; } -/// Function: variable_sensitivity_domaint::ai_simplify -/// -/// \param condition: the expression to simplify -/// \param ns: the namespace -/// \param lhs: is the expression on the left hand side -/// -/// \return True if no simplification was made -/// -/// 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. bool variable_sensitivity_domaint::ai_simplify( exprt &condition, const namespacet &ns) const @@ -291,29 +243,16 @@ bool variable_sensitivity_domaint::ai_simplify( } } -/// Function: variable_sensitivity_domaint::is_bottom -/// -/// \return True if the domain is bottom (i.e. unreachable). -/// -/// Find out if the domain is currently unreachable. bool variable_sensitivity_domaint::is_bottom() const { return abstract_state.is_bottom(); } -/// Function: variable_sensitivity_domaint::is_top -/// -/// \return True if the domain is top -/// -/// Is the domain completely top at this state bool variable_sensitivity_domaint::is_top() const { return abstract_state.is_top(); } -/// Get symbols that have been modified since this domain and other -/// \param other: The domain that things may have been modified in -/// \return A list of symbols whose write location is different std::vector variable_sensitivity_domaint::get_modified_symbols( const variable_sensitivity_domaint &other) const { @@ -321,20 +260,6 @@ std::vector variable_sensitivity_domaint::get_modified_symbols( abstract_state, other.abstract_state); } -/// Function: variable_sensitivity_domaint::transform_function_call -/// -/// \param from: the location to transform from which is a function call -/// \param to: the destination of the transform -/// (potentially inside the function call) -/// \param ai: the abstract interpreter -/// \param ns: the namespace of the current state -/// -/// Used by variable_sensitivity_domaint::transform to handle -/// FUNCTION_CALL transforms. This is copying the values of the arguments -/// into new symbols corresponding to the declared parameter names. -/// -/// If the function call is opaque we currently top the return value -/// and the value of any things whose address is passed into the function. void variable_sensitivity_domaint::transform_function_call( locationt from, locationt to, @@ -457,14 +382,6 @@ void variable_sensitivity_domaint::transform_function_call( } } -/// Function: variable_sensitivity_domaint::ignore_function_call_transform -/// -/// \param function_id: the name of the function being called -/// -/// \return Returns true if the function should be ignored -/// -/// Used to specify which CPROVER internal functions should be skipped -/// over when doing function call transforms bool variable_sensitivity_domaint::ignore_function_call_transform( const irep_idt &function_id) const { @@ -481,16 +398,6 @@ bool variable_sensitivity_domaint::ignore_function_call_transform( ignored_internal_function.cend(); } -/// Perform a context aware merge of the changes that have been applied -/// between function_start and the current state. Anything that has not been -/// modified will be taken from the \p function_call domain. -/// \param function_call: The local of the merge - values from here will be -/// taken if they have not been modified -/// \param function_start: The base of the merge - changes that have been made -/// between here and the end will be retained. -/// \param function_end: The end of the merge - changes that have been made -/// between the start and here will be retained. -/// \param ns: The global namespace void variable_sensitivity_domaint::merge_three_way_function_return( const ai_domain_baset &function_call, const ai_domain_baset &function_start, @@ -533,11 +440,6 @@ void variable_sensitivity_domaint::merge_three_way_function_return( } } -/// Given a domain and some symbols, apply those symbols values -/// to the current domain -/// \param modified_symbols: The symbols to write -/// \param source: The domain to take the values from -/// \param ns: The global namespace void variable_sensitivity_domaint::apply_domain( std::vector modified_symbols, const variable_sensitivity_domaint &source, diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index 89453b52251..b65750ebb2a 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -74,6 +74,14 @@ class variable_sensitivity_domaint : public ai_domain_baset { public: + /// Compute the abstract transformer for a single instruction + /// + /// \param from: the instruction before the abstract domain + /// \param to: the instruction after the abstract domain + /// \param ai: the abstract interpreter + /// \param ns: the namespace + /// + /// \return none void transform( const irep_idt &function_from, locationt from, @@ -82,32 +90,72 @@ class variable_sensitivity_domaint : public ai_domain_baset ai_baset &ai, const namespacet &ns) override; - /// no states + /// Sets the domain to bottom (no states / unreachable). void make_bottom() override; - /// all states + /// Sets the domain to top (all states). void make_top() override; - /// a reasonable entry-point state + /// Set up a reasonable entry-point state void make_entry() override; + /// Basic text output of the abstract domain + /// + /// \param out: the output stream + /// \param ai: the abstract interpreter + /// \param ns: the namespace + /// + /// \return none void output(std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; void output(std::ostream &out) const; + /// Computes the join between "this" and "b". + /// + /// \param b: the other domain + /// \param from: it's preceding location + /// \param to: it's current location + /// + /// \return true if something has changed. virtual bool merge(const variable_sensitivity_domaint &b, locationt from, locationt to); + /// Perform a context aware merge of the changes that have been applied + /// between function_start and the current state. Anything that has not been + /// modified will be taken from the \p function_call domain. + /// \param function_call: The local of the merge - values from here will be + /// taken if they have not been modified + /// \param function_start: The base of the merge - changes that have been made + /// between here and the end will be retained. + /// \param function_end: The end of the merge - changes that have been made + /// between the start and here will be retained. + /// \param ns: The global namespace virtual void merge_three_way_function_return( const ai_domain_baset &function_call, const ai_domain_baset &function_start, const ai_domain_baset &function_end, const namespacet &ns); + /// 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. + /// + /// \param condition: the expression to simplify + /// \param ns: the namespace + /// \param lhs: is the expression on the left hand side + /// + /// \return True if no simplification was made bool ai_simplify(exprt &condition, const namespacet &ns) const override; + /// Find out if the domain is currently unreachable. + /// + /// \return True if the domain is bottom (i.e. unreachable). bool is_bottom() const override; + + /// Is the domain completely top at this state + /// + /// \return True if the domain is top bool is_top() const override; virtual abstract_object_pointert @@ -117,17 +165,43 @@ class variable_sensitivity_domaint : public ai_domain_baset } private: + /// Used by variable_sensitivity_domaint::transform to handle + /// FUNCTION_CALL transforms. This is copying the values of the arguments + /// into new symbols corresponding to the declared parameter names. + /// + /// If the function call is opaque we currently top the return value + /// and the value of any things whose address is passed into the function. + /// + /// \param from: the location to transform from which is a function call + /// \param to: the destination of the transform + /// (potentially inside the function call) + /// \param ai: the abstract interpreter + /// \param ns: the namespace of the current state void transform_function_call( locationt from, locationt to, ai_baset &ai, const namespacet &ns); + /// Used to specify which CPROVER internal functions should be skipped + /// over when doing function call transforms + /// + /// \param function_id: the name of the function being called + /// + /// \return Returns true if the function should be ignored bool ignore_function_call_transform(const irep_idt &function_id) const; + /// Get symbols that have been modified since this domain and other + /// \param other: The domain that things may have been modified in + /// \return A list of symbols whose write location is different std::vector get_modified_symbols(const variable_sensitivity_domaint &other) const; + /// Given a domain and some symbols, apply those symbols values + /// to the current domain + /// \param modified_symbols: The symbols to write + /// \param source: The domain to take the values from + /// \param ns: The global namespace void apply_domain( std::vector modified_symbols, const variable_sensitivity_domaint &target, diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp index 5ca467df824..01cdc1cd19d 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.cpp @@ -12,14 +12,6 @@ variable_sensitivity_object_factoryt variable_sensitivity_object_factoryt::s_instance; -/// Function: variable_sensitivity_object_factoryt::get_abstract_object_type -/// -/// \param type: the type of the variable the abstract object is -/// meant to represent -/// -/// \return An enum indicating the abstract object type to use. -/// -/// 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) { @@ -73,21 +65,6 @@ variable_sensitivity_object_factoryt::get_abstract_object_type(const typet type) return abstract_object_type; } -/// Function: variable_sensitivity_object_factoryt::get_abstract_object -/// -/// \param type: the type of the variable -/// \param top: whether the abstract object should be top in the -/// two-value domain -/// \param bottom: whether the abstract object should be bottom in the -/// two-value domain -/// \param e: if top and bottom are false this expression is used as the -/// starting pointer for the abstract object -/// \param ns: namespace, used when following the input type -/// -/// \return An abstract object of the appropriate type. -/// -/// Get the appropriate abstract object for the variable under -/// consideration. abstract_object_pointert variable_sensitivity_object_factoryt::get_abstract_object( const typet type, @@ -153,12 +130,6 @@ variable_sensitivity_object_factoryt::get_abstract_object( } } -/// Function: variable_sensitivity_object_factoryt::set_options -/// -/// \param options: the command line options -/// -/// 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( const vsd_configt &options) { diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index 29d058b6f6a..1cfd48bdc00 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -126,6 +126,20 @@ class variable_sensitivity_object_factoryt { return s_instance; } + + /// Get the appropriate abstract object for the variable under + /// consideration. + /// + /// \param type: the type of the variable + /// \param top: whether the abstract object should be top in the + /// two-value domain + /// \param bottom: whether the abstract object should be bottom in the + /// two-value domain + /// \param e: if top and bottom are false this expression is used as the + /// starting pointer for the abstract object + /// \param ns: namespace, used when following the input type + /// + /// \return An abstract object of the appropriate type. abstract_object_pointert get_abstract_object( const typet type, bool top, @@ -133,6 +147,11 @@ class variable_sensitivity_object_factoryt const exprt &e, const abstract_environmentt &environment, const namespacet &ns); + + /// Called once to record the appropriate variables from the command line + /// options so that they can be accessed easily when they are needed. + /// + /// \param options: the command line options void set_options(const vsd_configt &options); private: @@ -155,6 +174,13 @@ class variable_sensitivity_object_factoryt UNION_INSENSITIVE, VALUE_SET }; + + /// Decide which abstract object type to use for the variable in question. + /// + /// \param type: the type of the variable the abstract object is + /// meant to represent + /// + /// \return An enum indicating the abstract object type to use. ABSTRACT_OBJECT_TYPET get_abstract_object_type(const typet type); template abstract_object_pointert initialize_abstract_object( From 7a729408c8a098ffc119ad4c66718fcec5918732 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 21 Sep 2020 18:41:44 +0100 Subject: [PATCH 340/342] Fix issues and warnings raised by doxygen --- .../abstract_enviroment.cpp | 4 - .../abstract_enviroment.h | 14 +-- .../variable-sensitivity/abstract_object.h | 6 ++ .../array_abstract_object.h | 1 + .../constant_abstract_value.h | 14 +++ .../constant_array_abstract_object.h | 9 +- .../constant_pointer_abstract_object.cpp | 92 +++---------------- .../constant_pointer_abstract_object.h | 72 +++++++++++++++ .../full_struct_abstract_object.h | 7 ++ .../interval_abstract_value.h | 15 ++- .../pointer_abstract_object.cpp | 10 +- .../pointer_abstract_object.h | 8 +- .../struct_abstract_object.h | 8 ++ .../union_abstract_object.h | 6 ++ .../variable_sensitivity_domain.cpp | 50 ++++------ .../variable_sensitivity_domain.h | 11 +-- .../variable_sensitivity_object_factory.h | 17 ++-- 17 files changed, 199 insertions(+), 145 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index ff86d1b296c..6f7fb228e49 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -343,10 +343,6 @@ abstract_object_pointert abstract_environmentt::abstract_object_factory( 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 diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.h b/src/analyses/variable-sensitivity/abstract_enviroment.h index 5170b475405..2b3faf4fce3 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.h +++ b/src/analyses/variable-sensitivity/abstract_enviroment.h @@ -132,6 +132,7 @@ class abstract_environmentt /// \param top: does the type of the object start as top /// \param bottom: does the type of the object start as bottom in /// the two-value domain + /// \param ns: the current variable namespace /// /// \return The abstract object that has been created virtual abstract_object_pointert abstract_object_factory( @@ -143,7 +144,8 @@ class abstract_environmentt /// For converting constants in the program /// /// \param type: the type of the object whose state should be tracked - /// \param expr: the starting value of the symbol + /// \param e: the starting value of the symbol + /// \param ns: the current variable namespace /// /// \return The abstract object that has been created /// @@ -169,8 +171,6 @@ class abstract_environmentt /// /// \param havoc_string: diagnostic string to track down havoc causing. /// - /// \return None - /// /// Set the domain to top virtual void havoc(const std::string &havoc_string); @@ -235,8 +235,10 @@ class abstract_environmentt /// the two-value domain /// \param bottom: does the type of the object start as bottom in /// the two-value domain - /// \param expr: the starting value of the symbol if top and bottom - /// are both false + /// \param e: the starting value of the symbol if top and bottom + /// are both false + /// \param environment: the current environment (normally *this) + /// \param ns: the current variable namespace /// /// \return The abstract object that has been created abstract_object_pointert abstract_object_factory( @@ -244,7 +246,7 @@ class abstract_environmentt bool top, bool bottom, const exprt &e, - const abstract_environmentt &eviroment, + const abstract_environmentt &environment, const namespacet &ns) const; }; diff --git a/src/analyses/variable-sensitivity/abstract_object.h b/src/analyses/variable-sensitivity/abstract_object.h index 86a9b0dd544..91c851dfb86 100644 --- a/src/analyses/variable-sensitivity/abstract_object.h +++ b/src/analyses/variable-sensitivity/abstract_object.h @@ -149,6 +149,11 @@ class abstract_objectt : public std::enable_shared_from_this /// /// \param expr: the expression to evaluate and find the result of it. /// This will be the symbol referred to be op0() + /// \param operands: an abstract_object (pointer) that represent + /// the possible values of each operand + /// \param environment: the abstract environment in which the + /// expression is being evaluated + /// \param ns: the current variable namespace /// /// \return Returns the abstract_object representing the result of /// this expression to the maximum precision available. @@ -266,6 +271,7 @@ class abstract_objectt : public std::enable_shared_from_this /// the sensitivity of the output and is the object compared /// against to choose whether this merge changed anything /// \param op2: the second abstract object to merge + /// \param out_modifications: reference to a flag indicating modification /// /// \return The merged abstract object with the same sensitivity as the /// first parameter. out_modifications will be true if the resulting diff --git a/src/analyses/variable-sensitivity/array_abstract_object.h b/src/analyses/variable-sensitivity/array_abstract_object.h index 652de1866a8..d4f73fee432 100644 --- a/src/analyses/variable-sensitivity/array_abstract_object.h +++ b/src/analyses/variable-sensitivity/array_abstract_object.h @@ -98,6 +98,7 @@ class array_abstract_objectt : public abstract_objectt /// \param env: the environment /// \param index: the expression used to access the specific value /// in the array + /// \param ns: the current variable namespace /// /// \return An abstract object representing the value in the array virtual abstract_object_pointert read_index( diff --git a/src/analyses/variable-sensitivity/constant_abstract_value.h b/src/analyses/variable-sensitivity/constant_abstract_value.h index 0c62d4ab16b..fcbf209ff68 100644 --- a/src/analyses/variable-sensitivity/constant_abstract_value.h +++ b/src/analyses/variable-sensitivity/constant_abstract_value.h @@ -35,6 +35,20 @@ class constant_abstract_valuet : public abstract_valuet { } + /// Interface for transforms + /// + /// \param expr: the expression to evaluate and find the result of it. + /// This will be the symbol referred to be op0() + /// \param operands: an abstract_object (pointer) that represent + /// the possible values of each operand + /// \param environment: the abstract environment in which the + /// expression is being evaluated + /// \param ns: the current variable namespace + /// + /// \return Returns the abstract_object representing the result of + /// this expression to the maximum precision available. + /// + /// Uses the rewriter to constant fold expressions where possible. abstract_object_pointert expression_transform( const exprt &expr, const std::vector &operands, diff --git a/src/analyses/variable-sensitivity/constant_array_abstract_object.h b/src/analyses/variable-sensitivity/constant_array_abstract_object.h index 0bd46d66c71..faf749d5bcd 100644 --- a/src/analyses/variable-sensitivity/constant_array_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_array_abstract_object.h @@ -93,6 +93,7 @@ class constant_array_abstract_objectt : public array_abstract_objectt /// \param env: the environment /// \param index: the expression used to access the specific value /// in the array + /// \param ns: the namespace /// /// \return An abstract object representing the value in the array abstract_object_pointert read_index( @@ -139,10 +140,12 @@ class constant_array_abstract_objectt : public array_abstract_objectt /// object to TOP void make_top_internal() override; - /// Short hand method for creating a top element of the array + /// Evaluates the index and tries to convert it to a constant integer /// - /// \param environment: the abstract environment + /// \param index: the index expression showing where to access the array + /// \param env: the abstract environment /// \param ns: the namespace + /// \param out_index: the index if it can be converted to a constant /// /// \return An abstract object pointer of type type().subtype() (i.e. the /// type of the array's values). @@ -175,7 +178,7 @@ class constant_array_abstract_objectt : public array_abstract_objectt /// Short hand method for creating a top element of the array /// - /// \param environment: the abstract environment + /// \param env: the abstract environment /// \param ns: the namespace /// /// \return An abstract object pointer of type type().subtype() (i.e. the diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp index 796bdb6a45f..cb6582dce39 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.cpp @@ -14,46 +14,36 @@ #include #include -/// \param type: the type the abstract_object is representing constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( - const typet &t) - : pointer_abstract_objectt(t) + const typet &type) + : pointer_abstract_objectt(type) { - PRECONDITION(t.id() == ID_pointer); + PRECONDITION(type.id() == ID_pointer); } -/// \param type: the type the abstract_object is representing -/// \param top: is the abstract_object starting as top -/// \param bottom: is the abstract_object starting as bottom -/// -/// 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) - : pointer_abstract_objectt(t, tp, bttm) + const typet &type, + bool top, + bool bottom) + : pointer_abstract_objectt(type, top, bottom) { - PRECONDITION(t.id() == ID_pointer); + PRECONDITION(type.id() == ID_pointer); } -/// \param old: the abstract object to copy from constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( const constant_pointer_abstract_objectt &old) : pointer_abstract_objectt(old), value_stack(old.value_stack) { } -/// \param expr: the expression to use as the starting pointer for -/// an abstract object constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( - const exprt &e, + const exprt &expr, const abstract_environmentt &environment, const namespacet &ns) - : pointer_abstract_objectt(e, environment, ns), - value_stack(e, environment, ns) + : pointer_abstract_objectt(expr, environment, ns), + value_stack(expr, environment, ns) { - PRECONDITION(e.type().id() == ID_pointer); + PRECONDITION(expr.type().id() == ID_pointer); if(value_stack.is_top_value()) { make_top(); @@ -63,14 +53,7 @@ constant_pointer_abstract_objectt::constant_pointer_abstract_objectt( clear_top(); } } -/// 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 -/// -/// \param other: the pointer being merged -/// -/// \return Returns the result of the merge. + abstract_object_pointert constant_pointer_abstract_objectt::merge(abstract_object_pointert other) const { @@ -87,14 +70,6 @@ constant_pointer_abstract_objectt::merge(abstract_object_pointert other) const } } -/// Merges two constant pointers. If they are pointing at the same -/// value, we merge, otherwise we set to top. -/// -/// \param other: the pointer being merged -/// -/// \return 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. abstract_object_pointert constant_pointer_abstract_objectt::merge_constant_pointers( const constant_pointer_abstract_pointert other) const @@ -119,15 +94,6 @@ constant_pointer_abstract_objectt::merge_constant_pointers( } } -/// To try and find a constant expression for this abstract object -/// -/// \return 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. -/// exprt constant_pointer_abstract_objectt::to_constant() const { if(is_top() || is_bottom()) @@ -142,12 +108,6 @@ exprt constant_pointer_abstract_objectt::to_constant() const } } -/// Print the value of the pointer. Either NULL if nullpointer or -/// ptr -> ( output of what the pointer is pointing to). -/// -/// \param out: the stream to write to -/// \param ai: ? -/// \param ns: ? void constant_pointer_abstract_objectt::output( std::ostream &out, const ai_baset &ai, @@ -191,15 +151,6 @@ void constant_pointer_abstract_objectt::output( } } -/// 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. -/// -/// \param env: the environment -/// \param ns: the namespace -/// -/// \return An abstract object representing the value this pointer is pointing -/// to abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( const abstract_environmentt &env, const namespacet &ns) const @@ -218,23 +169,6 @@ abstract_object_pointert constant_pointer_abstract_objectt::read_dereference( } } -/// 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. -/// -/// \param environment: the environment -/// \param ns: the namespace -/// \param stack: the remaining stack -/// \param new_value: the value to write to the dereferenced pointer -/// \param 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 -/// -/// \return A modified abstract object representing this pointer after it -/// has been written to. sharing_ptrt constant_pointer_abstract_objectt::write_dereference( abstract_environmentt &environment, diff --git a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h index 73416e30874..e81eac82737 100644 --- a/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/constant_pointer_abstract_object.h @@ -23,26 +23,82 @@ class constant_pointer_abstract_objectt : public pointer_abstract_objectt constant_pointer_abstract_pointert; public: + /// \param type: the type the abstract_object is representing explicit constant_pointer_abstract_objectt(const typet &type); + /// \param type: the type the abstract_object is representing + /// \param top: is the abstract_object starting as top + /// \param bottom: is the abstract_object starting as bottom + /// + /// Start the abstract object at either top or bottom or neither + /// Asserts if both top and bottom are true constant_pointer_abstract_objectt(const typet &type, bool top, bool bottom); + /// \param old: the abstract object to copy from constant_pointer_abstract_objectt( const constant_pointer_abstract_objectt &old); + /// \param expr: the expression to use as the starting pointer for + /// an abstract object + /// \param environment: the environment in which we evaluate expr + /// \param ns: the current namespace constant_pointer_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, const namespacet &ns); + /// To try and find a constant expression for this abstract object + /// + /// \return 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. + /// exprt to_constant() const override; + + /// Print the value of the pointer. Either NULL if nullpointer or + /// ptr -> ( output of what the pointer is pointing to). + /// + /// \param out: the stream to write to + /// \param ai: the domain in which this object appears + /// given as ai_baset so that the interface is the same + /// across all domains + /// \param ns: the current namespace void output(std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; + /// 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. + /// + /// \param env: the environment + /// \param ns: the namespace + /// + /// \return An abstract object representing the value this pointer is pointing + /// to abstract_object_pointert read_dereference( const abstract_environmentt &env, const namespacet &ns) const override; + /// 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. + /// + /// \param environment: the environment + /// \param ns: the namespace + /// \param stack: the remaining stack + /// \param value: the value to write to the dereferenced pointer + /// \param 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 + /// + /// \return A modified abstract object representing this pointer after it + /// has been written to. sharing_ptrt write_dereference( abstract_environmentt &environment, const namespacet &ns, @@ -57,11 +113,27 @@ class constant_pointer_abstract_objectt : public pointer_abstract_objectt const namespacet &ns) const override; protected: + /// 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 + /// + /// \param op1: the pointer being merged + /// + /// \return Returns the result of the merge. abstract_object_pointert merge(abstract_object_pointert op1) const override; CLONE private: + /// Merges two constant pointers. If they are pointing at the same + /// value, we merge, otherwise we set to top. + /// + /// \param other: the pointer being merged + /// + /// \return 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. abstract_object_pointert merge_constant_pointers(const constant_pointer_abstract_pointert other) const; diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.h b/src/analyses/variable-sensitivity/full_struct_abstract_object.h index 4bccc23a1ff..c6a058ea9e2 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.h @@ -45,6 +45,8 @@ class full_struct_abstract_objectt : public struct_abstract_objectt /// \param expr: the expression to use as the starting pointer for an /// abstract object + /// \param environment: the environment in which we evaluate expr + /// \param ns: the current namespace full_struct_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, @@ -108,6 +110,7 @@ class full_struct_abstract_objectt : public struct_abstract_objectt /// /// \param environment: the abstract environment /// \param member_expr: the expression uses to access a specific component + /// \param ns: the current namespace /// /// \return The abstract object representing the value of that /// component. For this abstraction this will always be top @@ -122,9 +125,13 @@ class full_struct_abstract_objectt : public struct_abstract_objectt /// update what they are storing for a specific component. /// /// \param environment: the abstract environment + /// \param ns: the current namespace /// \param stack: the remaining stack of expressions on the LHS to evaluate /// \param member_expr: the expression uses to access a specific component /// \param value: the value we are trying to write to the component + /// \param merging_write: whether to over-write or to merge with the + /// current value. In other words is there + /// any certainty that this write will happen. /// /// \return The struct_abstract_objectt representing the result of /// writing to a specific component. In this case this will diff --git a/src/analyses/variable-sensitivity/interval_abstract_value.h b/src/analyses/variable-sensitivity/interval_abstract_value.h index 2c31cf29329..f0a1ebd8e83 100644 --- a/src/analyses/variable-sensitivity/interval_abstract_value.h +++ b/src/analyses/variable-sensitivity/interval_abstract_value.h @@ -43,7 +43,20 @@ class interval_abstract_valuet : public abstract_valuet exprt to_constant() const override; - // Interface for transforms + /// Interface for transforms + /// + /// \param expr: the expression to evaluate and find the result of it. + /// This will be the symbol referred to be op0() + /// \param operands: an abstract_object (pointer) that represent + /// the possible values of each operand + /// \param environment: the abstract environment in which the + /// expression is being evaluated + /// \param ns: the current variable namespace + /// + /// \return Returns the abstract_object representing the result of + /// this expression to the maximum precision available. + /// + /// Perform the interval transforms abstract_object_pointert expression_transform( const exprt &expr, const std::vector &operands, diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp index d68a48d3e29..63b75a38c3f 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.cpp @@ -19,12 +19,12 @@ pointer_abstract_objectt::pointer_abstract_objectt(const typet &t) } pointer_abstract_objectt::pointer_abstract_objectt( - const typet &t, - bool tp, - bool bttm) - : abstract_objectt(t, tp, bttm) + const typet &type, + bool top, + bool bottom) + : abstract_objectt(type, top, bottom) { - PRECONDITION(t.id() == ID_pointer); + PRECONDITION(type.id() == ID_pointer); } pointer_abstract_objectt::pointer_abstract_objectt( diff --git a/src/analyses/variable-sensitivity/pointer_abstract_object.h b/src/analyses/variable-sensitivity/pointer_abstract_object.h index 656f38bb657..e89bc3d13f9 100644 --- a/src/analyses/variable-sensitivity/pointer_abstract_object.h +++ b/src/analyses/variable-sensitivity/pointer_abstract_object.h @@ -6,7 +6,8 @@ \*******************************************************************/ -/// \file The base of all pointer abstractions +/// \file +/// The base of all pointer abstractions #ifndef CPROVER_ANALYSES_VARIABLE_SENSITIVITY_POINTER_ABSTRACT_OBJECT_H #define CPROVER_ANALYSES_VARIABLE_SENSITIVITY_POINTER_ABSTRACT_OBJECT_H @@ -34,8 +35,11 @@ class pointer_abstract_objectt : public abstract_objectt /// \param expr: the expression to use as the starting pointer for /// an abstract object + /// \param environment: the environment in which the pointer is being + /// created + /// \param ns: the current namespace explicit pointer_abstract_objectt( - const exprt &e, + const exprt &expr, const abstract_environmentt &environment, const namespacet &ns); diff --git a/src/analyses/variable-sensitivity/struct_abstract_object.h b/src/analyses/variable-sensitivity/struct_abstract_object.h index 0a3029c5f18..d20d9ac2bbb 100644 --- a/src/analyses/variable-sensitivity/struct_abstract_object.h +++ b/src/analyses/variable-sensitivity/struct_abstract_object.h @@ -34,6 +34,9 @@ class struct_abstract_objectt : public abstract_objectt /// \param expr: the expression to use as the starting pointer for /// an abstract object + /// \param environment: the environment in which the pointer is being + /// created + /// \param ns: the current namespace explicit struct_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, @@ -95,6 +98,7 @@ class struct_abstract_objectt : public abstract_objectt /// /// \param environment: the abstract environment /// \param member_expr: the expression uses to access a specific component + /// \param ns: the current namespace /// /// \return The abstract object representing the value of that component. For /// this abstraction this will always be top since we are not tracking @@ -110,9 +114,13 @@ class struct_abstract_objectt : public abstract_objectt /// update what they are storing for a specific component. /// /// \param environment: the abstract environment + /// \param ns: the current namespace /// \param stack: the remaining stack of expressions on the LHS to evaluate /// \param member_expr: the expression uses to access a specific component /// \param value: the value we are trying to write to the component + /// \param merging_write: whether to over-write or to merge with the + /// current value. In other words is there + /// any certainty that this write will happen. /// /// \return The struct_abstract_objectt representing the result of writing /// to a specific component. In this case this will always be top diff --git a/src/analyses/variable-sensitivity/union_abstract_object.h b/src/analyses/variable-sensitivity/union_abstract_object.h index c20a0fc2147..69c947af72d 100644 --- a/src/analyses/variable-sensitivity/union_abstract_object.h +++ b/src/analyses/variable-sensitivity/union_abstract_object.h @@ -36,6 +36,7 @@ class union_abstract_objectt : public abstract_objectt /// an abstract object /// \param environment: the environment the abstract object is going /// to be evaluated in. + /// \param ns: the current namespace explicit union_abstract_objectt( const exprt &expr, const abstract_environmentt &environment, @@ -91,6 +92,7 @@ class union_abstract_objectt : public abstract_objectt /// /// \param environment: the abstract environment /// \param member_expr: the expression uses to access a specific component + /// \param ns: the current namespace /// /// The abstract object representing the value of that component. For /// this abstraction this will always be top since we are not tracking @@ -105,9 +107,13 @@ class union_abstract_objectt : public abstract_objectt /// update what they are storing for a specific component. /// /// \param environment: the abstract environment + /// \param ns: the current namespace /// \param stack: the remaining stack of expressions on the LHS to evaluate /// \param member_expr: the expression uses to access a specific component /// \param value: the value we are trying to write to the component + /// \param merging_write: whether to over-write or to merge with the + /// current value. In other words is there + /// any certainty that this write will happen. /// /// \return The union_abstract_objectt representing the result of writing /// to a specific component. In this case this will always be top diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp index 6adad231d64..fb631ba1b87 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.cpp @@ -220,7 +220,7 @@ bool variable_sensitivity_domaint::ai_simplify( exprt &condition, const namespacet &ns) const { - sharing_ptrt res = abstract_state.eval(condition, ns); + abstract_object_pointert res = abstract_state.eval(condition, ns); exprt c = res->to_constant(); if(c.id() == ID_nil) @@ -404,40 +404,30 @@ void variable_sensitivity_domaint::merge_three_way_function_return( const ai_domain_baset &function_end, const namespacet &ns) { - // TODO(tkiley): flag to turn of the context aware merge - if(true) - { - const variable_sensitivity_domaint &cast_function_call = - static_cast(function_call); + const variable_sensitivity_domaint &cast_function_call = + static_cast(function_call); - const variable_sensitivity_domaint &cast_function_start = - static_cast(function_start); + const variable_sensitivity_domaint &cast_function_start = + static_cast(function_start); - const variable_sensitivity_domaint &cast_function_end = - static_cast(function_end); + const variable_sensitivity_domaint &cast_function_end = + static_cast(function_end); - const std::vector &modified_symbol_names = - cast_function_start.get_modified_symbols(cast_function_end); + const std::vector &modified_symbol_names = + cast_function_start.get_modified_symbols(cast_function_end); - std::vector modified_symbols; - modified_symbols.reserve(modified_symbol_names.size()); - std::transform( - modified_symbol_names.begin(), - modified_symbol_names.end(), - std::back_inserter(modified_symbols), - [&ns](const irep_idt &id) { return ns.lookup(id).symbol_expr(); }); + std::vector modified_symbols; + modified_symbols.reserve(modified_symbol_names.size()); + std::transform( + modified_symbol_names.begin(), + modified_symbol_names.end(), + std::back_inserter(modified_symbols), + [&ns](const irep_idt &id) { return ns.lookup(id).symbol_expr(); }); - abstract_state = cast_function_call.abstract_state; - apply_domain(modified_symbols, cast_function_end, ns); - } - else - { - UNREACHABLE; // This case is not handled but also is not currently used - /* - ai_domain_baset::merge_three_way_function_return( - function_call, function_start, function_end, ns); - */ - } + abstract_state = cast_function_call.abstract_state; + apply_domain(modified_symbols, cast_function_end, ns); + + return; } void variable_sensitivity_domaint::apply_domain( diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h index b65750ebb2a..eda719e1c34 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_domain.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_domain.h @@ -46,7 +46,7 @@ /// 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 +/// 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 @@ -76,12 +76,12 @@ class variable_sensitivity_domaint : public ai_domain_baset public: /// Compute the abstract transformer for a single instruction /// + /// \param function_from: the name of the function containing from /// \param from: the instruction before the abstract domain + /// \param function_to: the name of the function containing to /// \param to: the instruction after the abstract domain /// \param ai: the abstract interpreter /// \param ns: the namespace - /// - /// \return none void transform( const irep_idt &function_from, locationt from, @@ -104,8 +104,6 @@ class variable_sensitivity_domaint : public ai_domain_baset /// \param out: the output stream /// \param ai: the abstract interpreter /// \param ns: the namespace - /// - /// \return none void output(std::ostream &out, const ai_baset &ai, const namespacet &ns) const override; @@ -143,7 +141,6 @@ class variable_sensitivity_domaint : public ai_domain_baset /// /// \param condition: the expression to simplify /// \param ns: the namespace - /// \param lhs: is the expression on the left hand side /// /// \return True if no simplification was made bool ai_simplify(exprt &condition, const namespacet &ns) const override; @@ -200,7 +197,7 @@ class variable_sensitivity_domaint : public ai_domain_baset /// Given a domain and some symbols, apply those symbols values /// to the current domain /// \param modified_symbols: The symbols to write - /// \param source: The domain to take the values from + /// \param target: The domain to take the values from /// \param ns: The global namespace void apply_domain( std::vector modified_symbols, diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h index 1cfd48bdc00..02ea4553e1f 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h +++ b/src/analyses/variable-sensitivity/variable_sensitivity_object_factory.h @@ -137,6 +137,7 @@ class variable_sensitivity_object_factoryt /// two-value domain /// \param e: if top and bottom are false this expression is used as the /// starting pointer for the abstract object + /// \param environment: the current abstract environment /// \param ns: namespace, used when following the input type /// /// \return An abstract object of the appropriate type. @@ -205,7 +206,6 @@ class variable_sensitivity_object_factoryt /// Function: variable_sensitivity_object_factoryt::initialize_abstract_object /// Initialize the abstract object class and return it. /// -/// \param abstract_object_classt: the class to use for the abstract object /// \param type: the type of the variable /// \param top: whether the abstract object should be top in the /// two-value domain @@ -213,6 +213,7 @@ class variable_sensitivity_object_factoryt /// two-value domain /// \param e: if top and bottom are false this expression is used as the /// starting pointer for the abstract object +/// \param environment: the current abstract environment /// \param ns: namespace, used when following the input type /// /// \return An abstract object of the appropriate type. @@ -224,17 +225,17 @@ variable_sensitivity_object_factoryt::initialize_abstract_object( bool top, bool bottom, const exprt &e, - const abstract_environmentt &enviroment, + const abstract_environmentt &environment, const namespacet &ns) { if(configuration.context_tracking.data_dependency_context) return initialize_context_abstract_object< abstract_object_classt, - data_dependency_contextt>(type, top, bottom, e, enviroment, ns); + data_dependency_contextt>(type, top, bottom, e, environment, ns); if(configuration.context_tracking.last_write_context) return initialize_context_abstract_object< abstract_object_classt, - write_location_contextt>(type, top, bottom, e, enviroment, ns); + write_location_contextt>(type, top, bottom, e, environment, ns); else { if(top || bottom) @@ -246,7 +247,7 @@ variable_sensitivity_object_factoryt::initialize_abstract_object( { PRECONDITION(type == ns.follow(e.type())); return abstract_object_pointert( - new abstract_object_classt(e, enviroment, ns)); + new abstract_object_classt(e, environment, ns)); } } } @@ -258,7 +259,7 @@ variable_sensitivity_object_factoryt::initialize_context_abstract_object( bool top, bool bottom, const exprt &e, - const abstract_environmentt &enviroment, + const abstract_environmentt &environment, const namespacet &ns) { if(top || bottom) @@ -273,9 +274,9 @@ variable_sensitivity_object_factoryt::initialize_context_abstract_object( { PRECONDITION(type == ns.follow(e.type())); return abstract_object_pointert(new context_classt( - abstract_object_pointert(new abstract_object_classt(e, enviroment, ns)), + abstract_object_pointert(new abstract_object_classt(e, environment, ns)), e, - enviroment, + environment, ns)); } } From 41606b01dccd683b6bacec39e32f9f1c6dd980f0 Mon Sep 17 00:00:00 2001 From: martin Date: Mon, 19 Oct 2020 16:42:23 +0100 Subject: [PATCH 341/342] Update regression tests to cope with changes to initialisation A recent PR has removed a couple of the in-built global variables that are used for modelling the C standard library. This has a knock on effect for the line numbers in the tests of dependency graphs. --- .../constant_propagation_01/test-vsd.desc | 4 +- .../constant_propagation_02/test-vsd.desc | 4 +- .../constant_propagation_03/test-vsd.desc | 4 +- .../constant_propagation_04/test-vsd.desc | 4 +- .../constant_propagation_07/test-vsd.desc | 4 +- .../constant_propagation_08/test-vsd.desc | 4 +- .../constant_propagation_11/test-vsd.desc | 4 +- .../constant_propagation_11/test.desc | 4 +- .../constant_propagation_12/test-vsd.desc | 4 +- .../test.desc | 56 ++++++------- .../test.desc | 54 ++++++------- .../test.desc | 64 +++++++-------- .../test.desc | 78 +++++++++---------- .../test.desc | 6 +- .../test.desc | 52 ++++++------- .../test.desc | 52 ++++++------- .../test.desc | 2 +- 17 files changed, 200 insertions(+), 200 deletions(-) diff --git a/regression/goto-analyzer/constant_propagation_01/test-vsd.desc b/regression/goto-analyzer/constant_propagation_01/test-vsd.desc index a857ab86251..2259a9f01cc 100644 --- a/regression/goto-analyzer/constant_propagation_01/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_01/test-vsd.desc @@ -3,7 +3,7 @@ main.c --variable-sensitivity --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ -^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 18, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 7, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 17, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_02/test-vsd.desc b/regression/goto-analyzer/constant_propagation_02/test-vsd.desc index 1b81e99291d..090c7d3b26e 100644 --- a/regression/goto-analyzer/constant_propagation_02/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_02/test-vsd.desc @@ -3,7 +3,7 @@ main.c --variable-sensitivity --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 1, assigns: 9, function calls: 0$ -^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 17, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 16, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_03/test-vsd.desc b/regression/goto-analyzer/constant_propagation_03/test-vsd.desc index 1b81e99291d..090c7d3b26e 100644 --- a/regression/goto-analyzer/constant_propagation_03/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_03/test-vsd.desc @@ -3,7 +3,7 @@ main.c --variable-sensitivity --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 1, assigns: 9, function calls: 0$ -^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 17, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 16, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_04/test-vsd.desc b/regression/goto-analyzer/constant_propagation_04/test-vsd.desc index 1b81e99291d..090c7d3b26e 100644 --- a/regression/goto-analyzer/constant_propagation_04/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_04/test-vsd.desc @@ -3,7 +3,7 @@ main.c --variable-sensitivity --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 1, assigns: 9, function calls: 0$ -^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 17, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 16, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_07/test-vsd.desc b/regression/goto-analyzer/constant_propagation_07/test-vsd.desc index c313d50afe1..d58e42e198b 100644 --- a/regression/goto-analyzer/constant_propagation_07/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_07/test-vsd.desc @@ -3,7 +3,7 @@ main.c --variable-sensitivity --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 3, assigns: 10, function calls: 0$ -^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 19, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 3, assigns: 9, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 18, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_08/test-vsd.desc b/regression/goto-analyzer/constant_propagation_08/test-vsd.desc index d2239d80583..ebc46cfd84f 100644 --- a/regression/goto-analyzer/constant_propagation_08/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_08/test-vsd.desc @@ -3,7 +3,7 @@ main.c --variable-sensitivity --vsd-arrays --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 2, assigns: 9, function calls: 0$ -^Unmodified: assert: 0, assume: 0, goto: 3, assigns: 18, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 2, assigns: 8, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 3, assigns: 17, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_11/test-vsd.desc b/regression/goto-analyzer/constant_propagation_11/test-vsd.desc index 57fde6c2fd6..7324b882f4f 100644 --- a/regression/goto-analyzer/constant_propagation_11/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_11/test-vsd.desc @@ -3,7 +3,7 @@ main.c --variable-sensitivity --vsd-arrays --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 1, assigns: 9, function calls: 0$ -^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 15, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 14, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_11/test.desc b/regression/goto-analyzer/constant_propagation_11/test.desc index e3e66e103ff..a095b629bdb 100644 --- a/regression/goto-analyzer/constant_propagation_11/test.desc +++ b/regression/goto-analyzer/constant_propagation_11/test.desc @@ -3,7 +3,7 @@ main.c --constants --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 1, assigns: 9, function calls: 0$ -^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 15, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 14, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/constant_propagation_12/test-vsd.desc b/regression/goto-analyzer/constant_propagation_12/test-vsd.desc index 1ba76308b8d..d4209868c6c 100644 --- a/regression/goto-analyzer/constant_propagation_12/test-vsd.desc +++ b/regression/goto-analyzer/constant_propagation_12/test-vsd.desc @@ -3,7 +3,7 @@ main.c --variable-sensitivity --simplify out.gb ^EXIT=0$ ^SIGNAL=0$ -^Simplified: assert: 1, assume: 0, goto: 1, assigns: 8, function calls: 0$ -^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 16, function calls: 2$ +^Simplified: assert: 1, assume: 0, goto: 1, assigns: 7, function calls: 0$ +^Unmodified: assert: 0, assume: 0, goto: 1, assigns: 15, function calls: 2$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc index 8118d3636c0..49bf22bca7e 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-arrays/test.desc @@ -8,31 +8,31 @@ activate-multi-line-match main#return_value \(\) -> TOP @ \[1\] __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] -__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[10\] -__CPROVER_malloc_object \(\) -> TOP @ \[12\] -__CPROVER_malloc_size \(\) -> 0ull? @ \[13\] -__CPROVER_memory_leak \(\) -> TOP @ \[15\] -__CPROVER_next_thread_id \(\) -> 0ul @ \[16\] -__CPROVER_pipe_count \(\) -> 0u @ \[18\] -__CPROVER_rounding_mode \(\) -> 0 @ \[19\] -__CPROVER_thread_id \(\) -> 0ul @ \[20\] -__CPROVER_threads_exited \(\) -> TOP @ \[23\] -do_arrays::1::bool_ \(\) -> TOP @ \[25\] -do_arrays::1::bool_1 \(\) -> TOP @ \[26\] -do_arrays::1::bool_2 \(\) -> TOP @ \[27\] -do_arrays::1::x \(\) -> \{\[0\] = 10 @ \[29\]\n\} @ \[29\] -do_arrays::1::x \(\) -> \{\[0\] = 10 @ \[29\]\n\[1\] = 20 @ \[30\]\n\} @ \[30\] -do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[31\]\n\[1\] = 20 @ \[30\]\n\} @ \[31\] -do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[31\]\n\[1\] = 40 @ \[32\]\n\} @ \[32\] -do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[31\]\n\[1\] = 30 @ \[33\]\n\} @ \[33\] -do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[34\]\n\[1\] = 30 @ \[33\]\n\} @ \[34\] -do_arrays::1::x \(\) -> \{\[0\] = 5 @ \[35\]\n\[1\] = 30 @ \[33\]\n\} @ \[35\] -do_arrays::1::x \(\) -> \{\[0\] = 15 @ \[36\]\n\[1\] = 30 @ \[33\]\n\} @ \[36\] -do_arrays::1::x \(\) -> \{\[0\] = 15 @ \[36\]\n\[1\] = 10 @ \[37\]\n\} @ \[37\] -do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[39\]\n\[1\] = 10 @ \[37\]\n\} @ \[39\] -do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[39\, 41\]\n\[1\] = 10 @ \[37\]\n\} @ \[39\, 41\] -do_arrays::1::x \(\) -> \{\[0\] = 0 @ \[43]\n\[1\] = 10 @ \[37\]\n\} @ \[43\] -do_arrays::1::x \(\) -> \{\[0\] = 3 @ \[45]\n\[1\] = 10 @ \[37\]\n\} @ \[45\] -do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[45\, 47]\n\[1\] = 10 @ \[37\]\n\} @ \[45\, 47\] -do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[45\, 47\, 50]\n\[1\] = 10 @ \[52\]\n\} @ \[52\] -do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[53]\n\[1\] = 10 @ \[52\]\n\} @ \[53\] +__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[9\] +__CPROVER_malloc_object \(\) -> TOP @ \[10\] +__CPROVER_malloc_size \(\) -> 0ull? @ \[11\] +__CPROVER_memory_leak \(\) -> TOP @ \[13\] +__CPROVER_next_thread_key \(\) -> 0ul @ \[15\] +__CPROVER_pipe_count \(\) -> 0u @ \[16\] +__CPROVER_rounding_mode \(\) -> 0 @ \[17\] +__CPROVER_thread_id \(\) -> 0ul @ \[18\] +__CPROVER_threads_exited \(\) -> TOP @ \[21\] +do_arrays::1::bool_ \(\) -> TOP @ \[23\] +do_arrays::1::bool_1 \(\) -> TOP @ \[24\] +do_arrays::1::bool_2 \(\) -> TOP @ \[25\] +do_arrays::1::x \(\) -> \{\[0\] = 10 @ \[27\]\n\} @ \[27\] +do_arrays::1::x \(\) -> \{\[0\] = 10 @ \[27\]\n\[1\] = 20 @ \[28\]\n\} @ \[28\] +do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[29\]\n\[1\] = 20 @ \[28\]\n\} @ \[29\] +do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[29\]\n\[1\] = 40 @ \[30\]\n\} @ \[30\] +do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[29\]\n\[1\] = 30 @ \[31\]\n\} @ \[31\] +do_arrays::1::x \(\) -> \{\[0\] = 30 @ \[32\]\n\[1\] = 30 @ \[31\]\n\} @ \[32\] +do_arrays::1::x \(\) -> \{\[0\] = 5 @ \[33\]\n\[1\] = 30 @ \[31\]\n\} @ \[33\] +do_arrays::1::x \(\) -> \{\[0\] = 15 @ \[34\]\n\[1\] = 30 @ \[31\]\n\} @ \[34\] +do_arrays::1::x \(\) -> \{\[0\] = 15 @ \[34\]\n\[1\] = 10 @ \[35\]\n\} @ \[35\] +do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[37\]\n\[1\] = 10 @ \[35\]\n\} @ \[37\] +do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[37\, 39\]\n\[1\] = 10 @ \[35\]\n\} @ \[37\, 39\] +do_arrays::1::x \(\) -> \{\[0\] = 0 @ \[41]\n\[1\] = 10 @ \[35\]\n\} @ \[41\] +do_arrays::1::x \(\) -> \{\[0\] = 3 @ \[43]\n\[1\] = 10 @ \[35\]\n\} @ \[43\] +do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[43\, 45]\n\[1\] = 10 @ \[35\]\n\} @ \[43\, 45\] +do_arrays::1::x \(\) -> \{\[0\] = TOP @ \[43\, 45\, 48]\n\[1\] = 10 @ \[50\]\n\} @ \[50\] +do_arrays::1::x \(\) -> \{\[0\] = 20 @ \[51]\n\[1\] = 10 @ \[50\]\n\} @ \[51\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc index 3fcd125d09b..e5b107c0156 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-pointers/test.desc @@ -8,30 +8,30 @@ activate-multi-line-match main#return_value \(\) -> TOP @ \[1\] __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] -__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[10\] -__CPROVER_malloc_object \(\) -> TOP @ \[12\] -__CPROVER_malloc_size \(\) -> 0ull? @ \[13\] -__CPROVER_memory_leak \(\) -> TOP @ \[15\] -__CPROVER_next_thread_id \(\) -> 0ul @ \[16\] -__CPROVER_pipe_count \(\) -> 0u @ \[18\] -__CPROVER_rounding_mode \(\) -> 0 @ \[19\] -__CPROVER_thread_id \(\) -> 0ul @ \[20\] -__CPROVER_threads_exited \(\) -> TOP @ \[23\] -do_pointers::1::bool_ \(\) -> TOP @ \[25\] -do_pointers::1::bool_1 \(\) -> TOP @ \[26\] -do_pointers::1::bool_2 \(\) -> TOP @ \[27\] -do_pointers::1::x \(\) -> TOP @ \[28\] -do_pointers::1::x \(\) -> 10 @ \[29\] -do_pointers::1::x_p \(\) -> TOP @ \[30\] -do_pointers::1::y \(\) -> TOP @ \[31\] -do_pointers::1::y \(\) -> 20 @ \[32\] -do_pointers::1::y_p \(\) -> TOP @ \[33\] -do_pointers::1::x_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[34\] -do_pointers::1::x \(\) -> 30 @ \[35\] -do_pointers::1::x \(\) -> 40 @ \[36\] -do_pointers::1::x \(\) -> TOP @ \[37\] -do_pointers::1::x \(\) -> 50 @ \[38\] -do_pointers::1::y_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[39\] -do_pointers::1::x \(\) -> 60 @ \[40\] -do_pointers::1::j \(\) -> TOP @ \[41\] -do_pointers::1::j \(\) -> 60 @ \[42\] +__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[9\] +__CPROVER_malloc_object \(\) -> TOP @ \[10\] +__CPROVER_malloc_size \(\) -> 0ull? @ \[11\] +__CPROVER_memory_leak \(\) -> TOP @ \[13\] +__CPROVER_next_thread_id \(\) -> 0ul @ \[14\] +__CPROVER_pipe_count \(\) -> 0u @ \[16\] +__CPROVER_rounding_mode \(\) -> 0 @ \[17\] +__CPROVER_thread_id \(\) -> 0ul @ \[18\] +__CPROVER_threads_exited \(\) -> TOP @ \[21\] +do_pointers::1::bool_ \(\) -> TOP @ \[23\] +do_pointers::1::bool_1 \(\) -> TOP @ \[24\] +do_pointers::1::bool_2 \(\) -> TOP @ \[25\] +do_pointers::1::x \(\) -> TOP @ \[26\] +do_pointers::1::x \(\) -> 10 @ \[27\] +do_pointers::1::x_p \(\) -> TOP @ \[28\] +do_pointers::1::y \(\) -> TOP @ \[29\] +do_pointers::1::y \(\) -> 20 @ \[30\] +do_pointers::1::y_p \(\) -> TOP @ \[31\] +do_pointers::1::x_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[32\] +do_pointers::1::x \(\) -> 30 @ \[33\] +do_pointers::1::x \(\) -> 40 @ \[34\] +do_pointers::1::x \(\) -> TOP @ \[35\] +do_pointers::1::x \(\) -> 50 @ \[36\] +do_pointers::1::y_p \(\) -> ptr ->\(do_pointers::1::x\) @ \[37\] +do_pointers::1::x \(\) -> 60 @ \[38\] +do_pointers::1::j \(\) -> TOP @ \[39\] +do_pointers::1::j \(\) -> 60 @ \[40\] diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc index 3b778cc9310..e575ef34cc1 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-structs/test.desc @@ -8,36 +8,36 @@ activate-multi-line-match main#return_value \(\) -> TOP @ \[1\] __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] -__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[10\] -__CPROVER_malloc_object \(\) -> TOP @ \[12\] -__CPROVER_malloc_size \(\) -> 0ull? @ \[13\] -__CPROVER_memory_leak \(\) -> TOP @ \[15\] -__CPROVER_next_thread_id \(\) -> 0ul @ \[16\] -__CPROVER_pipe_count \(\) -> 0u @ \[18\] -__CPROVER_rounding_mode \(\) -> 0 @ \[19\] -__CPROVER_thread_id \(\) -> 0ul @ \[20\] -__CPROVER_threads_exited \(\) -> TOP @ \[23\] -do_structs::1::bool_ \(\) -> TOP @ \[25\] -do_structs::1::bool_1 \(\) -> TOP @ \[26\] -do_structs::1::bool_2 \(\) -> TOP @ \[27\] -do_structs::1::st \(\) -> \{\} @ \[28\] -do_structs::1::st \(\) -> \{.x=10 @ \[29\]\} @ \[29\] -do_structs::1::st \(\) -> \{.x=10 @ \[29\]\, .y=20 @ \[30\]\} @ \[30\] -do_structs::1::st \(\) -> \{.x=30 @ \[31\]\, .y=20 @ \[30\]\} @ \[31\] -do_structs::1::st \(\) -> \{.x=30 @ \[31\]\, .y=40 @ \[32\]\} @ \[32\] -do_structs::1::st \(\) -> \{.x=30 @ \[31\]\, .y=30 @ \[33\]\} @ \[33\] -do_structs::1::st \(\) -> \{.x=30 @ \[34\]\, .y=30 @ \[33\]\} @ \[34\] -do_structs::1::st \(\) -> \{.x=5 @ \[35\]\, .y=30 @ \[33\]\} @ \[35\] -do_structs::1::st \(\) -> \{.x=15 @ \[36\]\, .y=30 @ \[33\]\} @ \[36\] -do_structs::1::st \(\) -> \{.x=15 @ \[36\]\, .y=10 @ \[37\]\} @ \[37\] -do_structs::1::st \(\) -> \{.x=20 @ \[39\]\, .y=10 @ \[37\]\} @ \[39\] -do_structs::1::st \(\) -> \{.x=20 @ \[39\, 41\]\, .y=10 @ \[37\]\} @ \[39\, 41\] -do_structs::1::st \(\) -> \{.x=0 @ \[43\]\, .y=10 @ \[37\]\} @ \[43\] -do_structs::1::st \(\) -> \{.x=3 @ \[45\]\, .y=10 @ \[37\]\} @ \[45\] -do_structs::1::st \(\) -> \{.x=TOP @ \[45\, 47\]\, .y=10 @ \[37\]\} @ \[45\, 47\] -do_structs::1::st \(\) -> \{.x=TOP @ \[45\, 47\, 50\]\, .y=10 @ \[37\]\} @ \[45\, 47\, 50\] -do_structs::1::st \(\) -> \{.x=TOP @ \[45\, 47\, 50\]\, .y=10 @ \[52\]\} @ \[52\] -do_structs::1::st \(\) -> \{.x=20 @ \[53\]\, .y=10 @ \[52\]\} @ \[53\] -do_structs::1::new_age \(\) -> \{\} @ \[54\] -do_structs::1::new_age \(\) -> \{.x=20 @ \[55\]\, .y=10 @ \[55\]\} @ \[55\] +__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[9\] +__CPROVER_malloc_object \(\) -> TOP @ \[10\] +__CPROVER_malloc_size \(\) -> 0ull? @ \[11\] +__CPROVER_memory_leak \(\) -> TOP @ \[13\] +__CPROVER_next_thread_id \(\) -> 0ul @ \[14\] +__CPROVER_pipe_count \(\) -> 0u @ \[16\] +__CPROVER_rounding_mode \(\) -> 0 @ \[17\] +__CPROVER_thread_id \(\) -> 0ul @ \[18\] +__CPROVER_threads_exited \(\) -> TOP @ \[21\] +do_structs::1::bool_ \(\) -> TOP @ \[23\] +do_structs::1::bool_1 \(\) -> TOP @ \[24\] +do_structs::1::bool_2 \(\) -> TOP @ \[25\] +do_structs::1::st \(\) -> \{\} @ \[26\] +do_structs::1::st \(\) -> \{.x=10 @ \[27\]\} @ \[27\] +do_structs::1::st \(\) -> \{.x=10 @ \[27\]\, .y=20 @ \[28\]\} @ \[28\] +do_structs::1::st \(\) -> \{.x=30 @ \[29\]\, .y=20 @ \[28\]\} @ \[29\] +do_structs::1::st \(\) -> \{.x=30 @ \[29\]\, .y=40 @ \[30\]\} @ \[30\] +do_structs::1::st \(\) -> \{.x=30 @ \[29\]\, .y=30 @ \[31\]\} @ \[31\] +do_structs::1::st \(\) -> \{.x=30 @ \[32\]\, .y=30 @ \[31\]\} @ \[32\] +do_structs::1::st \(\) -> \{.x=5 @ \[33\]\, .y=30 @ \[31\]\} @ \[33\] +do_structs::1::st \(\) -> \{.x=15 @ \[34\]\, .y=30 @ \[31\]\} @ \[34\] +do_structs::1::st \(\) -> \{.x=15 @ \[34\]\, .y=10 @ \[35\]\} @ \[35\] +do_structs::1::st \(\) -> \{.x=20 @ \[37\]\, .y=10 @ \[35\]\} @ \[37\] +do_structs::1::st \(\) -> \{.x=20 @ \[37\, 39\]\, .y=10 @ \[35\]\} @ \[37\, 39\] +do_structs::1::st \(\) -> \{.x=0 @ \[41\]\, .y=10 @ \[35\]\} @ \[41\] +do_structs::1::st \(\) -> \{.x=3 @ \[43\]\, .y=10 @ \[35\]\} @ \[43\] +do_structs::1::st \(\) -> \{.x=TOP @ \[43\, 45\]\, .y=10 @ \[35\]\} @ \[43\, 45\] +do_structs::1::st \(\) -> \{.x=TOP @ \[43\, 45\, 48\]\, .y=10 @ \[35\]\} @ \[43\, 45\, 48\] +do_structs::1::st \(\) -> \{.x=TOP @ \[43\, 45\, 48\]\, .y=10 @ \[50\]\} @ \[50\] +do_structs::1::st \(\) -> \{.x=20 @ \[51\]\, .y=10 @ \[50\]\} @ \[51\] +do_structs::1::new_age \(\) -> \{\} @ \[52\] +do_structs::1::new_age \(\) -> \{.x=20 @ \[53\]\, .y=10 @ \[53\]\} @ \[53\] -- diff --git a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc index 7a8963718b2..498891f5696 100644 --- a/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc +++ b/regression/goto-analyzer/sensitivity-last-written-locations-variables/test.desc @@ -7,43 +7,43 @@ main#return_value \(\) -> TOP @ \[1\] __CPROVER_alloca_object \(\) -> TOP @ \[4\] __CPROVER_dead_object \(\) -> TOP @ \[5\] __CPROVER_deallocated \(\) -> TOP @ \[6\] -__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[10\] -__CPROVER_malloc_object \(\) -> TOP @ \[12\] -__CPROVER_malloc_size \(\) -> 0ull? @ \[13\] -__CPROVER_memory_leak \(\) -> TOP @ \[15\] -__CPROVER_next_thread_id \(\) -> 0ul @ \[16\] -__CPROVER_next_thread_key \(\) -> 0ul @ \[17\] -__CPROVER_pipe_count \(\) -> 0u @ \[18\] -__CPROVER_rounding_mode \(\) -> 0 @ \[19\] -__CPROVER_thread_id \(\) -> 0ul @ \[20\] -__CPROVER_thread_key_dtors \(\) -> TOP @ \[21\] -__CPROVER_thread_keys \(\) -> TOP @ \[22\] -__CPROVER_threads_exited \(\) -> TOP @ \[23\] -global_x \(\) -> 0 @ \[24\] -do_variables::1::bool_ \(\) -> TOP @ \[26\] -do_variables::1::bool_1 \(\) -> TOP @ \[27\] -do_variables::1::bool_2 \(\) -> TOP @ \[28\] -global_x \(\) -> 5 @ \[29\] -do_variables::1::x \(\) -> TOP @ \[30\] -do_variables::1::x \(\) -> 10 @ \[31\] -do_variables::1::y \(\) -> TOP @ \[32\] -do_variables::1::y \(\) -> 20 @ \[33\] -do_variables::1::x \(\) -> 30 @ \[34\] -do_variables::1::y \(\) -> 40 @ \[35\] -do_variables::1::y \(\) -> 30 @ \[36\] -do_variables::1::x \(\) -> 30 @ \[37\] -do_variables::1::x \(\) -> 5 @ \[38\] -do_variables::1::x \(\) -> 15 @ \[39\] -do_variables::1::y \(\) -> 10 @ \[40\] -do_variables::1::x \(\) -> 20 @ \[42\] -do_variables::1::x \(\) -> 20 @ \[42\, 44\] -do_variables::1::x \(\) -> 50 @ \[46\] -do_variables::1::x \(\) -> 20 @ \[48\] -do_variables::1::x \(\) -> TOP @ \[48\, 50\] -do_variables::1::x \(\) -> 0 @ \[52\] -do_variables::1::x \(\) -> 3 @ \[54\] -do_variables::1::x \(\) -> TOP @ \[54\, 56\] -do_variables::1::x \(\) -> TOP @ \[54\, 56\, 59\] -do_variables::1::y \(\) -> 10 @ \[61\] -do_variables::1::x \(\) -> 20 @ \[62\] +__CPROVER_malloc_is_new_array \(\) -> FALSE @ \[9\] +__CPROVER_malloc_object \(\) -> TOP @ \[10\] +__CPROVER_malloc_size \(\) -> 0ull? @ \[11\] +__CPROVER_memory_leak \(\) -> TOP @ \[13\] +__CPROVER_next_thread_id \(\) -> 0ul @ \[14\] +__CPROVER_next_thread_key \(\) -> 0ul @ \[15\] +__CPROVER_pipe_count \(\) -> 0u @ \[16\] +__CPROVER_rounding_mode \(\) -> 0 @ \[17\] +__CPROVER_thread_id \(\) -> 0ul @ \[18\] +__CPROVER_thread_key_dtors \(\) -> TOP @ \[19\] +__CPROVER_thread_keys \(\) -> TOP @ \[20\] +__CPROVER_threads_exited \(\) -> TOP @ \[21\] +global_x \(\) -> 0 @ \[22\] +do_variables::1::bool_ \(\) -> TOP @ \[24\] +do_variables::1::bool_1 \(\) -> TOP @ \[25\] +do_variables::1::bool_2 \(\) -> TOP @ \[26\] +global_x \(\) -> 5 @ \[27\] +do_variables::1::x \(\) -> TOP @ \[28\] +do_variables::1::x \(\) -> 10 @ \[29\] +do_variables::1::y \(\) -> TOP @ \[30\] +do_variables::1::y \(\) -> 20 @ \[31\] +do_variables::1::x \(\) -> 30 @ \[32\] +do_variables::1::y \(\) -> 40 @ \[33\] +do_variables::1::y \(\) -> 30 @ \[34\] +do_variables::1::x \(\) -> 30 @ \[35\] +do_variables::1::x \(\) -> 5 @ \[36\] +do_variables::1::x \(\) -> 15 @ \[37\] +do_variables::1::y \(\) -> 10 @ \[38\] +do_variables::1::x \(\) -> 20 @ \[40\] +do_variables::1::x \(\) -> 20 @ \[40\, 42\] +do_variables::1::x \(\) -> 50 @ \[44\] +do_variables::1::x \(\) -> 20 @ \[46\] +do_variables::1::x \(\) -> TOP @ \[46\, 48\] +do_variables::1::x \(\) -> 0 @ \[50\] +do_variables::1::x \(\) -> 3 @ \[52\] +do_variables::1::x \(\) -> TOP @ \[52\, 54\] +do_variables::1::x \(\) -> TOP @ \[52\, 54\, 57\] +do_variables::1::y \(\) -> 10 @ \[59\] +do_variables::1::x \(\) -> 20 @ \[60\] -- diff --git a/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc b/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc index 9ea9f78f523..f2f3dcdc1b7 100644 --- a/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc +++ b/regression/goto-analyzer/sensitivity-test-data-dependency-context/test.desc @@ -5,8 +5,8 @@ data-dependency-context.c activate-multi-line-match ^EXIT=0$ ^SIGNAL=0$ -st \(\) -> \{.a=.* @ \[2, 57\]\[Data dependencies: 57, 2\]\[Data dominators: \], .b=.* @ \[5, 57\]\[Data dependencies: 57, 5\]\[Data dominators: \]\} @ \[2, 5, 57\]\[Data dependencies: 57, 5, 2\]\[Data dominators: 57\] -ar \(\) -> \{\[0\] = TOP @ \[11\, 51\]\[Data dependencies: 51\, 11\]\[Data dominators: \]\n\[1\] = TOP @ \[14\, 51\]\[Data dependencies: 51\, 14\]\[Data dominators: \]\n\} @ \[11\, 14\, 51\]\[Data dependencies: 51\, 14\, 11\]\[Data dominators: 51\] -arr \(\) -> \{\[0\] = 1 @ \[19\]\[Data dependencies: 19\]\[Data dominators: 19\]\n\[1\] = 2 @ \[20\]\[Data dependencies: 20\]\[Data dominators: 20\]\n\[2\] = TOP @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: \]\n\} @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: 52\] +st \(\) -> \{.a=.* @ \[2, 55\]\[Data dependencies: 55, 2\]\[Data dominators: \], .b=.* @ \[5, 55\]\[Data dependencies: 55, 5\]\[Data dominators: \]\} @ \[2, 5, 55\]\[Data dependencies: 55, 5, 2\]\[Data dominators: 55\] +ar \(\) -> \{\[0\] = TOP @ \[11\, 49\]\[Data dependencies: 49\, 11\]\[Data dominators: \]\n\[1\] = TOP @ \[14\, 49\]\[Data dependencies: 49\, 14\]\[Data dominators: \]\n\} @ \[11\, 14\, 49\]\[Data dependencies: 49\, 14\, 11\]\[Data dominators: 49\] +arr \(\) -> \{\[0\] = 1 @ \[19\]\[Data dependencies: 19\]\[Data dominators: 19\]\n\[1\] = 2 @ \[20\]\[Data dependencies: 20\]\[Data dominators: 20\]\n\[2\] = TOP @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: \]\n\} @ \[21, 23\]\[Data dependencies: 23, 21\]\[Data dominators: 50\] -- ^warning: ignoring diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc index 0268705cfbe..13ab739f402 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph-toyota/test.desc @@ -3,35 +3,35 @@ main.c file1.c file2.c --dependence-graph-vs --vsd-structs --vsd-arrays --show ^EXIT=0$ ^SIGNAL=0$ -Data dependencies: 63 \[st.a\] -Data dependencies: 63 \[st.b\] -Data dependencies: 1 \[st.a\], 63 \[st.a\] -Data dependencies: 4 \[st.b\], 63 \[st.b\] -Data dependencies: 1 \[st.a\], 4 \[st.b\], 63 \[st.a, st.b\] -Data dependencies: 57 \[ar\[\([^)]*\)0\]\] -Data dependencies: 57 \[ar\[\([^)]*\)1\]\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\] -Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\] +Data dependencies: 61 \[st.a\] +Data dependencies: 61 \[st.b\] +Data dependencies: 1 \[st.a\], 61 \[st.a\] +Data dependencies: 4 \[st.b\], 61 \[st.b\] +Data dependencies: 1 \[st.a\], 4 \[st.b\], 61 \[st.a, st.b\] +Data dependencies: 55 \[ar\[\([^)]*\)0\]\] +Data dependencies: 55 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 55 \[ar\[\([^)]*\)0\]\] +Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\] Data dependencies: 19 \[arr\[\([^)]*\)1\]\] Data dependencies: 18 \[arr\[\([^)]*\)0\]\] Data dependencies: 19 \[arr\[\([^)]*\)1\]\] Data dependencies: 20 \[arr\[\([^)]*\)2\]\], 22 \[arr\[\([^)]*\)2\]\] -Data dependencies: 1 \[st.a\], 63 \[st.a\], 67 \[st.a\] -Data dependencies: 4 \[st.b\], 63 \[st.b\], 70 \[st.b\] -Data dependencies: 1 \[st.a\], 4 \[st.b\], 63 \[st.a, st.b\], 67 \[st.a\], 70 \[st.b\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\], 78 \[ar\[\([^)]*\)0\]\] -Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\], 81 \[ar\[\([^)]*\)1\]\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 78 \[ar\[\([^)]*\)0\]\], 81 \[ar\[\([^)]*\)1\]\] -Data dependencies: 1 \[st.a\], 63 \[st.a\] -Data dependencies: 4 \[st.b\], 63 \[st.b\] -Data dependencies: 1 \[st.a\], 63 \[st.a\], 67 \[st.a\] -Data dependencies: 4 \[st.b\], 63 \[st.b\], 70 \[st.b\] -Data dependencies: 1 \[st.a\], 4 \[st.b\], 63 \[st.a, st.b\], 67 \[st.a\], 70 \[st.b\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\] -Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\], 78 \[ar\[\([^)]*\)0\]\] -Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\], 81 \[ar\[\([^)]*\)1\]\] -Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 78 \[ar\[\([^)]*\)0\]\], 81 \[ar\[\([^)]*\)1\]\] +Data dependencies: 1 \[st.a\], 61 \[st.a\], 65 \[st.a\] +Data dependencies: 4 \[st.b\], 61 \[st.b\], 68 \[st.b\] +Data dependencies: 1 \[st.a\], 4 \[st.b\], 61 \[st.a, st.b\], 65 \[st.a\], 68 \[st.b\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 55 \[ar\[\([^)]*\)0\]\], 76 \[ar\[\([^)]*\)0\]\] +Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)1\]\], 79 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 76 \[ar\[\([^)]*\)0\]\], 79 \[ar\[\([^)]*\)1\]\] +Data dependencies: 1 \[st.a\], 61 \[st.a\] +Data dependencies: 4 \[st.b\], 61 \[st.b\] +Data dependencies: 1 \[st.a\], 61 \[st.a\], 65 \[st.a\] +Data dependencies: 4 \[st.b\], 61 \[st.b\], 68 \[st.b\] +Data dependencies: 1 \[st.a\], 4 \[st.b\], 61 \[st.a, st.b\], 65 \[st.a\], 68 \[st.b\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 55 \[ar\[\([^)]*\)0\]\] +Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 55 \[ar\[\([^)]*\)0\]\], 76 \[ar\[\([^)]*\)0\]\] +Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)1\]\], 79 \[ar\[\([^)]*\)1\]\] +Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 76 \[ar\[\([^)]*\)0\]\], 79 \[ar\[\([^)]*\)1\]\] -- ^warning: ignoring diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc index ff7855759f1..61cdcb706db 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph/test.desc @@ -3,36 +3,36 @@ main.c file1.c file2.c --dependence-graph-vs --vsd-structs --vsd-arrays --show ^EXIT=0$ ^SIGNAL=0$ -^Data dependencies: 63 \[st.a\]$ -^Data dependencies: 63 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 63 \[st.a\]$ -^Data dependencies: 4 \[st.b\], 63 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 4 \[st.b\], 63 \[st.a, st.b\]$ -^Data dependencies: 57 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 61 \[st.a\]$ +^Data dependencies: 61 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 61 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 61 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 4 \[st.b\], 61 \[st.a, st.b\]$ +^Data dependencies: 55 \[ar\[\([^)]*\)0\]\]$ ^Data dependencies: 6 \[out1\]$ -^Data dependencies: 57 \[ar\[\([^)]*\)1\]\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\]$ -^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\]$ +^Data dependencies: 55 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 55 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\]$ ^Data dependencies: 19 \[arr\[\([^)]*\)1\]\]$ ^Data dependencies: 18 \[arr\[\([^)]*\)0\]\]$ ^Data dependencies: 19 \[arr\[\([^)]*\)1\]\]$ ^Data dependencies: 20 \[arr\[\([^)]*\)2\]\], 22 \[arr\[\([^)]*\)2\]\]$ -^Data dependencies: 1 \[st.a\], 63 \[st.a\], 67 \[st.a\]$ -^Data dependencies: 4 \[st.b\], 63 \[st.b\], 70 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 4 \[st.b\], 63 \[st.a, st.b\], 67 \[st.a\], 70 \[st.b\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\], 78 \[ar\[\([^)]*\)0\]\]$ -^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\], 81 \[ar\[\([^)]*\)1\]\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 78 \[ar\[\([^)]*\)0\]\], 81 \[ar\[\([^)]*\)1\]\]$ -^Data dependencies: 1 \[st.a\], 63 \[st.a\]$ -^Data dependencies: 4 \[st.b\], 63 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 63 \[st.a\], 67 \[st.a\]$ -^Data dependencies: 4 \[st.b\], 63 \[st.b\], 70 \[st.b\]$ -^Data dependencies: 1 \[st.a\], 4 \[st.b\], 63 \[st.a, st.b\], 67 \[st.a\], 70 \[st.b\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\]$ -^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 57 \[ar\[\([^)]*\)0\]\], 78 \[ar\[\([^)]*\)0\]\]$ -^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)1\]\], 81 \[ar\[\([^)]*\)1\]\]$ -^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 57 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 78 \[ar\[\([^)]*\)0\]\], 81 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 1 \[st.a\], 61 \[st.a\], 65 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 61 \[st.b\], 68 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 4 \[st.b\], 61 \[st.a, st.b\], 65 \[st.a\], 68 \[st.b\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 55 \[ar\[\([^)]*\)0\]\], 76 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)1\]\], 79 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 76 \[ar\[\([^)]*\)0\]\], 79 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 1 \[st.a\], 61 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 61 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 61 \[st.a\], 65 \[st.a\]$ +^Data dependencies: 4 \[st.b\], 61 \[st.b\], 68 \[st.b\]$ +^Data dependencies: 1 \[st.a\], 4 \[st.b\], 61 \[st.a, st.b\], 65 \[st.a\], 68 \[st.b\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 55 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 55 \[ar\[\([^)]*\)0\]\], 76 \[ar\[\([^)]*\)0\]\]$ +^Data dependencies: 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)1\]\], 79 \[ar\[\([^)]*\)1\]\]$ +^Data dependencies: 10 \[ar\[\([^)]*\)0\]\], 13 \[ar\[\([^)]*\)1\]\], 55 \[ar\[\([^)]*\)0\], ar\[\([^)]*\)1\]\], 76 \[ar\[\([^)]*\)0\]\], 79 \[ar\[\([^)]*\)1\]\]$ -- ^warning: ignoring diff --git a/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc index d8564343ea4..a509f3ec3fe 100644 --- a/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc +++ b/regression/goto-analyzer/variable-sensitivity-dependence-graph17/test.desc @@ -4,5 +4,5 @@ main.c activate-multi-line-match ^EXIT=0$ ^SIGNAL=0$ -\*\*\*\* 9 file .*main\.c line 22 function main\nControl dependencies: 39 \[UNCONDITIONAL\]\nData dependencies: 1 \[g_a\[\([^)]*\)i\]\], 2 \[g_a\[\([^)]*\)i\]\], 3 \[g_a\[\([^)]*\)i\]\], 7 \[g_a\[\([^)]*\)i\]\] +\*\*\*\* 9 file .*main\.c line 22 function main\nControl dependencies: 37 \[UNCONDITIONAL\]\nData dependencies: 1 \[g_a\[\([^)]*\)i\]\], 2 \[g_a\[\([^)]*\)i\]\], 3 \[g_a\[\([^)]*\)i\]\], 7 \[g_a\[\([^)]*\)i\]\] -- From 22f775c891fd8a0b135d222e288106214f3a9a2e Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 10 Nov 2020 21:34:22 +0000 Subject: [PATCH 342/342] s/const auto/const auto &/ in loops This was inefficient but now causes build failures on OS X as it uses -Werror -Wrange-loop-analysis --- src/analyses/variable-sensitivity/abstract_enviroment.cpp | 2 +- src/analyses/variable-sensitivity/data_dependency_context.cpp | 4 ++-- .../variable-sensitivity/full_struct_abstract_object.cpp | 2 +- .../variable_sensitivity_dependence_graph.cpp | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/analyses/variable-sensitivity/abstract_enviroment.cpp b/src/analyses/variable-sensitivity/abstract_enviroment.cpp index 6f7fb228e49..bf3cba22e6c 100644 --- a/src/analyses/variable-sensitivity/abstract_enviroment.cpp +++ b/src/analyses/variable-sensitivity/abstract_enviroment.cpp @@ -474,7 +474,7 @@ abstract_environmentt::modified_symbols( first.map.get_view(view); for(const auto &entry : view) { - const auto second_entry = second.map.find(entry.first); + const auto &second_entry = second.map.find(entry.first); if(second_entry.has_value()) { if(second_entry.value().get()->has_been_modified(entry.second)) diff --git a/src/analyses/variable-sensitivity/data_dependency_context.cpp b/src/analyses/variable-sensitivity/data_dependency_context.cpp index f647bdc958b..ea3072d3d7c 100644 --- a/src/analyses/variable-sensitivity/data_dependency_context.cpp +++ b/src/analyses/variable-sensitivity/data_dependency_context.cpp @@ -318,7 +318,7 @@ std::set data_dependency_contextt::get_data_dependencies() const { std::set result; - for(const auto d : data_deps) + for(const auto &d : data_deps) result.insert(d); return result; } @@ -332,7 +332,7 @@ std::set data_dependency_contextt::get_data_dominators() const { std::set result; - for(const auto d : data_dominators) + for(const auto &d : data_dominators) result.insert(d); return result; } diff --git a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp index 20c2cae60bd..7453fe5eb1e 100644 --- a/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp +++ b/src/analyses/variable-sensitivity/full_struct_abstract_object.cpp @@ -213,7 +213,7 @@ void full_struct_abstract_objectt::output( bool first = true; out << "{"; - for(const auto field : type_decl.components()) + for(const auto &field : type_decl.components()) { auto value = map.find(field.get_name()); if(value.has_value()) diff --git a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp index 55e13dc04ce..877bff46724 100644 --- a/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp +++ b/src/analyses/variable-sensitivity/variable_sensitivity_dependence_graph.cpp @@ -34,7 +34,7 @@ void variable_sensitivity_dependence_domaint::eval_data_deps( { // If the expression was able to be eval'ed to something with data // dependencies, then that's all we need to gather. - for(const auto dep : res->get_data_dependencies()) + for(const auto &dep : res->get_data_dependencies()) deps[dep].insert(expr); } else @@ -188,7 +188,7 @@ void variable_sensitivity_dependence_domaint::data_dependencies( { const code_function_callt &call = to_code_function_call(to->code); const code_function_callt::argumentst &args = call.arguments(); - for(const auto arg : args) + for(const auto &arg : args) { eval_data_deps(arg, ns, domain_data_deps); }