From ccb371bde106caf78c6fc308088e7caf511949e7 Mon Sep 17 00:00:00 2001 From: johndumbell Date: Fri, 23 Mar 2018 10:49:01 +0000 Subject: [PATCH 01/93] Increase AssertionError arguments allowed from 2 to 3 There is a constructor for this class with 2 arguments plus implied this. --- src/goto-programs/builtin_functions.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/goto-programs/builtin_functions.cpp b/src/goto-programs/builtin_functions.cpp index a1dc45880ed..8780e092575 100644 --- a/src/goto-programs/builtin_functions.cpp +++ b/src/goto-programs/builtin_functions.cpp @@ -969,11 +969,11 @@ void goto_convertt::do_function_call_symbol( copy(function_call, FUNCTION_CALL, dest); - if(arguments.size()!=1 && arguments.size()!=2) + if(arguments.size() != 1 && arguments.size() != 2 && arguments.size() != 3) { error().source_location=function.find_source_location(); error() << "`" << identifier - << "' expected to have one or two arguments" << eom; + << "' expected to have one, two or three arguments" << eom; throw 0; } From 4d14b68b91c896b7d1c9371980d52a2a00fa1582 Mon Sep 17 00:00:00 2001 From: johndumbell Date: Wed, 11 Apr 2018 15:59:53 +0100 Subject: [PATCH 02/93] Add a regression test. --- .../AssertionIssue.class | Bin 0 -> 556 bytes .../AssertionIssue.java | 13 +++++++++++++ .../assertion_error_constructors/test.desc | 8 ++++++++ 3 files changed, 21 insertions(+) create mode 100644 regression/cbmc-java/assertion_error_constructors/AssertionIssue.class create mode 100644 regression/cbmc-java/assertion_error_constructors/AssertionIssue.java create mode 100644 regression/cbmc-java/assertion_error_constructors/test.desc diff --git a/regression/cbmc-java/assertion_error_constructors/AssertionIssue.class b/regression/cbmc-java/assertion_error_constructors/AssertionIssue.class new file mode 100644 index 0000000000000000000000000000000000000000..a9312303951fc670042fcc5d3a7346dcfd005cda GIT binary patch literal 556 zcmZWmO;5r=5Pb`ULPg|56h8xr2jBn)j~Ej}G$Cp903qSn;s%zKZL%#Af0ic_N%ZcI zGR{_0H11($=gphZhoFEVeI=v_uNjh!=7_=Q`H!4o&lZy3FBdLXLp@Jgwm)&ak)wpJ ze?TLg3DPLov3@@Ymb}Z554Cj+Ggt$EsV4kRXt8qKi1_Wf^W@~PgB(Lu-#eZor=6H| ztCX)8&IkU2lcSv0R$PX)kSirz@42>8zMQrh>hVM*d+~pLZE{Ml`%9z^wyqEEoKHfA zR>R(cgHVxe_ZJdtcbg;BVbZVACjqASptws_hccs_YOTRuqIRBQIs)k{(_K@EfC7q? vvna*GO+xi4Zjcz4k{cM~HBxJ&-wC80D1HkW Date: Wed, 11 Apr 2018 16:54:01 +0100 Subject: [PATCH 03/93] Update desc file to add pass variables. --- regression/cbmc-java/assertion_error_constructors/test.desc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/regression/cbmc-java/assertion_error_constructors/test.desc b/regression/cbmc-java/assertion_error_constructors/test.desc index c5b41d9ba22..fde9624618f 100644 --- a/regression/cbmc-java/assertion_error_constructors/test.desc +++ b/regression/cbmc-java/assertion_error_constructors/test.desc @@ -1,8 +1,8 @@ CORE AssertionIssue.class --function AssertionIssue.throwAssertion -^EXIT=0$ +^EXIT=10$ ^SIGNAL=0$ -^VERIFICATION SUCCESSFUL$ +^VERIFICATION FAILED$ -- ^warning: ignoring From d4c5c0c1c830d9fd8a0ed87aa2cd15392fdb0904 Mon Sep 17 00:00:00 2001 From: Marek Trtik Date: Wed, 22 Nov 2017 10:53:54 +0000 Subject: [PATCH 04/93] Fixing member offset computation in presence of bitfields The previous algorithm correctly identified the offset of the next non-bitfield member, but would fail on consecutive bit-fields (fitting in one byte) as the offset was eagerly incremented. Also cleanup this computation in all places that used a similar algorithm. --- regression/cbmc/Bitfields3/main.c | 53 ++++++++++++++++++++++++++++ regression/cbmc/Bitfields3/test.desc | 8 +++++ src/ansi-c/padding.cpp | 15 ++++---- src/util/pointer_offset_size.cpp | 23 +++++++----- 4 files changed, 82 insertions(+), 17 deletions(-) create mode 100644 regression/cbmc/Bitfields3/main.c create mode 100644 regression/cbmc/Bitfields3/test.desc diff --git a/regression/cbmc/Bitfields3/main.c b/regression/cbmc/Bitfields3/main.c new file mode 100644 index 00000000000..c3aa64072cb --- /dev/null +++ b/regression/cbmc/Bitfields3/main.c @@ -0,0 +1,53 @@ +#include +#include + +#pragma pack(1) +struct A +{ + unsigned char a; + unsigned char b : 2; + unsigned char c : 2; + unsigned char d; +}; + +struct B +{ + unsigned char a; + unsigned char b : 2; + unsigned char c; + unsigned char d : 2; +}; + +struct C +{ + unsigned char a; + unsigned char b : 4; + unsigned char c : 4; + unsigned char d; +}; +#pragma pack() + +int main(void) +{ + assert(sizeof(struct A) == 3); + struct A *p = malloc(3); + assert((unsigned char *)p + 2 == &(p->d)); + p->c = 3; + if(p->c != 3) + { + free(p); + } + free(p); + + assert(sizeof(struct B) == 4); + struct B *pb = malloc(4); + assert((unsigned char *)pb + 2 == &(pb->c)); + free(pb); + + assert(sizeof(struct C) == 3); + struct C *pc = malloc(3); + assert((unsigned char *)pc + 2 == &(pc->d)); + free(pc); + + return 0; +} diff --git a/regression/cbmc/Bitfields3/test.desc b/regression/cbmc/Bitfields3/test.desc new file mode 100644 index 00000000000..96c9b4bcd7b --- /dev/null +++ b/regression/cbmc/Bitfields3/test.desc @@ -0,0 +1,8 @@ +CORE +main.c +--pointer-check --bounds-check +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/src/ansi-c/padding.cpp b/src/ansi-c/padding.cpp index 3b87a6190d8..3139df62e52 100644 --- a/src/ansi-c/padding.cpp +++ b/src/ansi-c/padding.cpp @@ -199,9 +199,9 @@ void add_padding(struct_typet &type, const namespacet &ns) max_alignment=a; std::size_t w=to_c_bit_field_type(it_type).get_width(); - std::size_t bytes; - for(bytes=0; w>bit_field_bits; ++bytes, bit_field_bits+=8) {} - bit_field_bits-=w; + bit_field_bits += w; + const std::size_t bytes = bit_field_bits / 8; + bit_field_bits %= 8; offset+=bytes; continue; } @@ -209,6 +209,9 @@ void add_padding(struct_typet &type, const namespacet &ns) else a=alignment(it_type, ns); + DATA_INVARIANT( + bit_field_bits == 0, "padding ensures offset at byte boundaries"); + // check minimum alignment if(abit_field_bits; ++current.second, bit_field_bits+=8) {} - bit_field_bits-=w; + bit_field_bits += w; + current.second += bit_field_bits / 8; + bit_field_bits %= 8; } else { + DATA_INVARIANT( + bit_field_bits == 0, "padding ensures offset at byte boundaries"); const typet &subtype=comp.type(); mp_integer sub_size=pointer_offset_size(subtype, ns); if(sub_size==-1) @@ -287,13 +290,15 @@ exprt member_offset_expr( if(it->type().id()==ID_c_bit_field) { std::size_t w=to_c_bit_field_type(it->type()).get_width(); - std::size_t bytes; - for(bytes=0; w>bit_field_bits; ++bytes, bit_field_bits+=8) {} - bit_field_bits-=w; + bit_field_bits += w; + const std::size_t bytes = bit_field_bits / 8; + bit_field_bits %= 8; result=plus_exprt(result, from_integer(bytes, result.type())); } else { + DATA_INVARIANT( + bit_field_bits == 0, "padding ensures offset at byte boundaries"); const typet &subtype=it->type(); exprt sub_size=size_of_expr(subtype, ns); if(sub_size.is_nil()) @@ -381,13 +386,15 @@ exprt size_of_expr( if(it->type().id()==ID_c_bit_field) { std::size_t w=to_c_bit_field_type(it->type()).get_width(); - std::size_t bytes; - for(bytes=0; w>bit_field_bits; ++bytes, bit_field_bits+=8) {} - bit_field_bits-=w; + bit_field_bits += w; + const std::size_t bytes = bit_field_bits / 8; + bit_field_bits %= 8; result=plus_exprt(result, from_integer(bytes, result.type())); } else { + DATA_INVARIANT( + bit_field_bits == 0, "padding ensures offset at byte boundaries"); const typet &subtype=it->type(); exprt sub_size=size_of_expr(subtype, ns); if(sub_size.is_nil()) From 4e2ce6c5b460722631bc1e11785c01e2bcbdbb6e Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Wed, 21 Feb 2018 18:27:52 +0000 Subject: [PATCH 05/93] Reset namespace after symbolic execution The state's symbol table may go out of scope, leaving the namespace with a dangling pointer. This is a follow-up to e8eec2c8a8. --- src/goto-symex/symex_main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 8c33d25541d..0a45365c296 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -208,6 +208,9 @@ void goto_symext::symex_with_state( // execution, so return the names generated through symbolic execution // through `new_symbol_table`. new_symbol_table = state.symbol_table; + // reset the namespace back to a sane state as state.symbol_table might go out + // of scope + ns = namespacet(outer_symbol_table); } void goto_symext::resume_symex_from_saved_state( From acc152e7f4ecf055b133a0ecf0f5131412ee0cce Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Fri, 23 Feb 2018 12:02:32 +0000 Subject: [PATCH 06/93] C front-end: Section/ASM renaming also needs to be applied to aliases The example taken from the Linux kernel shows that people mix weak aliases with section attributes. Not updating the alias name results in a namespace lookup failure. gcc_attributes11 is a reduced example taken from SV-COMP, where the same problem arises. --- regression/ansi-c/gcc_attributes11/main.c | 18 ++++++++++++++++++ regression/ansi-c/gcc_attributes11/test.desc | 8 ++++++++ regression/ansi-c/gcc_attributes9/main.c | 12 ++++++++++++ src/ansi-c/c_typecheck_base.cpp | 7 ++++++- 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 regression/ansi-c/gcc_attributes11/main.c create mode 100644 regression/ansi-c/gcc_attributes11/test.desc diff --git a/regression/ansi-c/gcc_attributes11/main.c b/regression/ansi-c/gcc_attributes11/main.c new file mode 100644 index 00000000000..b69ac3e0e63 --- /dev/null +++ b/regression/ansi-c/gcc_attributes11/main.c @@ -0,0 +1,18 @@ +#ifdef __GNUC__ +// example extracted from SV-COMP's ldv-linux-3.4-simple/ +// 32_7_cpp_false-unreach-call_single_drivers-net-phy-dp83640 +static int __attribute__((__section__(".init.text"))) +__attribute__((no_instrument_function)) dp83640_init(void) +{ + return 0; +} +int init_module(void) __attribute__((alias("dp83640_init"))); +#endif + +int main() +{ +#ifdef __GNUC__ + dp83640_init(); +#endif + return 0; +} diff --git a/regression/ansi-c/gcc_attributes11/test.desc b/regression/ansi-c/gcc_attributes11/test.desc new file mode 100644 index 00000000000..466da18b2b5 --- /dev/null +++ b/regression/ansi-c/gcc_attributes11/test.desc @@ -0,0 +1,8 @@ +CORE +main.c + +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring +^CONVERSION ERROR$ diff --git a/regression/ansi-c/gcc_attributes9/main.c b/regression/ansi-c/gcc_attributes9/main.c index f18e17aa773..76c7aeeca27 100644 --- a/regression/ansi-c/gcc_attributes9/main.c +++ b/regression/ansi-c/gcc_attributes9/main.c @@ -11,11 +11,23 @@ const char* __attribute__((section("s"))) __attribute__((weak)) bar(); volatile int __attribute__((__section__(".init.data1"))) txt_heap_base1; volatile int __attribute__((__section__(".init.data3"))) txt_heap_base, __attribute__((__section__(".init.data4"))) txt_heap_size; +int __attribute__((__section__(".init.text"))) __attribute__((__cold__)) +__alloc_bootmem_huge_page(void *h); +int __attribute__((__section__(".init.text"))) __attribute__((__cold__)) +alloc_bootmem_huge_page(void *h); +int alloc_bootmem_huge_page(void *h) + __attribute__((weak, alias("__alloc_bootmem_huge_page"))); +int __alloc_bootmem_huge_page(void *h) +{ + return 1; +} #endif int main() { #ifdef __GNUC__ + int r = alloc_bootmem_huge_page(0); + static int __attribute__((section(".data.unlikely"))) __warned; __warned=1; return __warned; diff --git a/src/ansi-c/c_typecheck_base.cpp b/src/ansi-c/c_typecheck_base.cpp index 1d213aa8f0a..ad72ea59f61 100644 --- a/src/ansi-c/c_typecheck_base.cpp +++ b/src/ansi-c/c_typecheck_base.cpp @@ -708,7 +708,12 @@ void c_typecheck_baset::typecheck_declaration( // alias function need not have been declared yet, thus // can't lookup - symbol.value=symbol_exprt(full_spec.alias); + // also cater for renaming/placement in sections + const auto &renaming_entry = asm_label_map.find(full_spec.alias); + if(renaming_entry == asm_label_map.end()) + symbol.value = symbol_exprt(full_spec.alias); + else + symbol.value = symbol_exprt(renaming_entry->second); symbol.is_macro=true; } From 401f01f765b66dee2ff39dc4467610e9376d3bb3 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Mon, 7 Aug 2017 09:30:21 +0000 Subject: [PATCH 07/93] fixup! Support __attribute__((section("x")) --- src/ansi-c/expr2c.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ansi-c/expr2c.cpp b/src/ansi-c/expr2c.cpp index 8e723404511..9a8a06ea799 100644 --- a/src/ansi-c/expr2c.cpp +++ b/src/ansi-c/expr2c.cpp @@ -8,6 +8,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "expr2c.h" +#include #include #include #include @@ -89,6 +90,9 @@ static std::string clean_identifier(const irep_idt &id) *it2='_'; } + // rewrite . as used in ELF section names + std::replace(dest.begin(), dest.end(), '.', '_'); + return dest; } From 176626fa1bfd0a96ae40f1ad9c933ebe62715128 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Fri, 16 Feb 2018 13:35:59 +0000 Subject: [PATCH 08/93] Only the top-level section should be considered for renaming The Linux kernel first places `jiffies64` in .data, and later refines that to .data..cacheline_aligned. The latter still is within the .data section, though, so just use the .data part for renaming. --- src/ansi-c/c_typecheck_base.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/ansi-c/c_typecheck_base.cpp b/src/ansi-c/c_typecheck_base.cpp index ad72ea59f61..890815fcc86 100644 --- a/src/ansi-c/c_typecheck_base.cpp +++ b/src/ansi-c/c_typecheck_base.cpp @@ -721,8 +721,18 @@ void c_typecheck_baset::typecheck_declaration( apply_asm_label(full_spec.asm_label, symbol); else { - std::string asm_name; - asm_name=id2string(full_spec.section)+"$$"; + // section name is not empty, do a bit of parsing + std::string asm_name = id2string(full_spec.section); + if(asm_name[0] != '.') + { + warning().source_location = symbol.location; + warning() << "section name `" << asm_name + << "' expected to start with `.'" << eom; + } + std::string::size_type primary_section = asm_name.find('.', 1); + if(primary_section != std::string::npos) + asm_name.resize(primary_section); + asm_name += "$$"; if(!full_spec.asm_label.empty()) asm_name+=id2string(full_spec.asm_label); else From 0e9443127fb471a0b537e70db50accacae03bd79 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 19 Apr 2018 17:07:15 +0100 Subject: [PATCH 09/93] Attribute main function arguments to __CPROVER_start These are created to serve as arguments to main() (or whatever --function was passed), but are declared in __CPROVER_start, and so should be named after their declarer like all other locals. This was causing a problem in the security repository, where we relied on local variable names being prefixed by their declaring function name, and the easiest fix was to restore that convention. --- src/java_bytecode/java_entry_point.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index 5c3beafc357..1597868caf2 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -203,7 +203,7 @@ exprt::operandst java_build_arguments( !assume_init_pointers_not_null && !is_main && !is_this; object_factory_parameterst parameters = object_factory_parameters; - parameters.function_id = function.name; + parameters.function_id = goto_functionst::entry_point(); // generate code to allocate and non-deterministicaly initialize the // argument From 684da28e5a263ec51297bf62551f4358f51ccc62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20G=C3=BCdemann?= Date: Sat, 21 Apr 2018 17:26:40 +0200 Subject: [PATCH 10/93] Fix CMake build for Glucose Syrup --- scripts/glucose-syrup-patch | 102 ++++++++++++++++++++++++++------- scripts/glucose_CMakeLists.txt | 2 + 2 files changed, 84 insertions(+), 20 deletions(-) diff --git a/scripts/glucose-syrup-patch b/scripts/glucose-syrup-patch index 138e4a50315..22b34562b8e 100644 --- a/scripts/glucose-syrup-patch +++ b/scripts/glucose-syrup-patch @@ -1,6 +1,6 @@ -diff -rupN glucose-syrup/core/Solver.cc glucose-syrup-patched/core/Solver.cc ---- glucose-syrup/core/Solver.cc 2014-10-03 10:10:21.000000000 +0100 -+++ glucose-syrup-patched/core/Solver.cc 2016-07-08 13:06:02.772186004 +0100 +diff -rupNw glucose-syrup/core/Solver.cc glucose-syrup-patched/core/Solver.cc +--- glucose-syrup/core/Solver.cc 2014-10-03 11:10:21.000000000 +0200 ++++ glucose-syrup-patched/core/Solver.cc 2018-04-21 16:58:22.950005391 +0200 @@ -931,7 +931,6 @@ void Solver::uncheckedEnqueue(Lit p, CRe CRef Solver::propagate() { CRef confl = CRef_Undef; @@ -19,9 +19,9 @@ diff -rupN glucose-syrup/core/Solver.cc glucose-syrup-patched/core/Solver.cc // Model found: return l_True; } -diff -rupN glucose-syrup/core/SolverTypes.h glucose-syrup-patched/core/SolverTypes.h ---- glucose-syrup/core/SolverTypes.h 2014-10-03 10:10:22.000000000 +0100 -+++ glucose-syrup-patched/core/SolverTypes.h 2016-07-08 13:06:02.772186004 +0100 +diff -rupNw glucose-syrup/core/SolverTypes.h glucose-syrup-patched/core/SolverTypes.h +--- glucose-syrup/core/SolverTypes.h 2014-10-03 11:10:22.000000000 +0200 ++++ glucose-syrup-patched/core/SolverTypes.h 2018-04-21 16:58:22.950005391 +0200 @@ -53,7 +53,9 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR #include @@ -32,9 +32,20 @@ diff -rupN glucose-syrup/core/SolverTypes.h glucose-syrup-patched/core/SolverTyp #include "mtl/IntTypes.h" #include "mtl/Alg.h" -diff -rupN glucose-syrup/mtl/IntTypes.h glucose-syrup-patched/mtl/IntTypes.h ---- glucose-syrup/mtl/IntTypes.h 2014-10-03 10:10:22.000000000 +0100 -+++ glucose-syrup-patched/mtl/IntTypes.h 2016-07-08 13:06:02.772186004 +0100 +@@ -170,7 +172,10 @@ class Clause { + unsigned lbd : BITS_LBD; + } header; + ++#include ++#include + union { Lit lit; float act; uint32_t abs; CRef rel; } data[0]; ++#include + + friend class ClauseAllocator; + +diff -rupNw glucose-syrup/mtl/IntTypes.h glucose-syrup-patched/mtl/IntTypes.h +--- glucose-syrup/mtl/IntTypes.h 2014-10-03 11:10:22.000000000 +0200 ++++ glucose-syrup-patched/mtl/IntTypes.h 2018-04-21 16:58:22.950005391 +0200 @@ -31,7 +31,9 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR #else @@ -45,10 +56,49 @@ diff -rupN glucose-syrup/mtl/IntTypes.h glucose-syrup-patched/mtl/IntTypes.h #endif -diff -rupN glucose-syrup/simp/SimpSolver.cc glucose-syrup-patched/simp/SimpSolver.cc ---- glucose-syrup/simp/SimpSolver.cc 2014-10-03 10:10:22.000000000 +0100 -+++ glucose-syrup-patched/simp/SimpSolver.cc 2016-07-08 13:07:00.396187548 +0100 -@@ -687,11 +687,11 @@ bool SimpSolver::eliminate(bool turn_off +diff -rupNw glucose-syrup/mtl/Vec.h glucose-syrup-patched/mtl/Vec.h +--- glucose-syrup/mtl/Vec.h 2014-10-03 11:10:22.000000000 +0200 ++++ glucose-syrup-patched/mtl/Vec.h 2018-04-21 16:58:22.950005391 +0200 +@@ -103,7 +103,7 @@ template + void vec::capacity(int min_cap) { + if (cap >= min_cap) return; + int add = imax((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2 +- if (add > INT_MAX - cap || ((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM) ++ if (add > INT_MAX - cap || (((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM)) + throw OutOfMemoryException(); + } + +diff -rupNw glucose-syrup/simp/SimpSolver.cc glucose-syrup-patched/simp/SimpSolver.cc +--- glucose-syrup/simp/SimpSolver.cc 2014-10-03 11:10:22.000000000 +0200 ++++ glucose-syrup-patched/simp/SimpSolver.cc 2018-04-21 16:58:22.950005391 +0200 +@@ -319,10 +319,13 @@ bool SimpSolver::merge(const Clause& _ps + if (var(qs[i]) != v){ + for (int j = 0; j < ps.size(); j++) + if (var(ps[j]) == var(qs[i])) ++ { + if (ps[j] == ~qs[i]) ++ + return false; + else + goto next; ++ } + out_clause.push(qs[i]); + } + next:; +@@ -353,10 +356,12 @@ bool SimpSolver::merge(const Clause& _ps + if (var(__qs[i]) != v){ + for (int j = 0; j < ps.size(); j++) + if (var(__ps[j]) == var(__qs[i])) ++ { + if (__ps[j] == ~__qs[i]) + return false; + else + goto next; ++ } + size++; + } + next:; +@@ -687,11 +692,11 @@ bool SimpSolver::eliminate(bool turn_off // int toPerform = clauses.size()<=4800000; @@ -62,7 +112,7 @@ diff -rupN glucose-syrup/simp/SimpSolver.cc glucose-syrup-patched/simp/SimpSolve while (toPerform && (n_touched > 0 || bwdsub_assigns < trail.size() || elim_heap.size() > 0)){ gatherTouchedClauses(); -@@ -760,10 +760,11 @@ bool SimpSolver::eliminate(bool turn_off +@@ -760,10 +765,11 @@ bool SimpSolver::eliminate(bool turn_off checkGarbage(); } @@ -75,9 +125,21 @@ diff -rupN glucose-syrup/simp/SimpSolver.cc glucose-syrup-patched/simp/SimpSolve return ok; -diff -rupN glucose-syrup/utils/ParseUtils.h glucose-syrup-patched/utils/ParseUtils.h ---- glucose-syrup/utils/ParseUtils.h 2014-10-03 10:10:22.000000000 +0100 -+++ glucose-syrup-patched/utils/ParseUtils.h 2016-07-08 13:06:02.772186004 +0100 +diff -rupNw glucose-syrup/utils/Options.h glucose-syrup-patched/utils/Options.h +--- glucose-syrup/utils/Options.h 2014-10-03 11:10:22.000000000 +0200 ++++ glucose-syrup-patched/utils/Options.h 2018-04-21 16:58:22.950005391 +0200 +@@ -60,7 +60,7 @@ class Option + struct OptionLt { + bool operator()(const Option* x, const Option* y) { + int test1 = strcmp(x->category, y->category); +- return test1 < 0 || test1 == 0 && strcmp(x->type_name, y->type_name) < 0; ++ return test1 < 0 || (test1 == 0 && strcmp(x->type_name, y->type_name) < 0); + } + }; + +diff -rupNw glucose-syrup/utils/ParseUtils.h glucose-syrup-patched/utils/ParseUtils.h +--- glucose-syrup/utils/ParseUtils.h 2014-10-03 11:10:22.000000000 +0200 ++++ glucose-syrup-patched/utils/ParseUtils.h 2018-04-21 16:58:22.950005391 +0200 @@ -25,7 +25,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR #include #include @@ -109,9 +171,9 @@ diff -rupN glucose-syrup/utils/ParseUtils.h glucose-syrup-patched/utils/ParseUti int operator * () const { return (pos >= size) ? EOF : buf[pos]; } void operator ++ () { pos++; assureLookahead(); } -diff -rupN glucose-syrup/utils/System.h glucose-syrup-patched/utils/System.h ---- glucose-syrup/utils/System.h 2014-10-03 10:10:22.000000000 +0100 -+++ glucose-syrup-patched/utils/System.h 2016-07-08 13:06:02.776186005 +0100 +diff -rupNw glucose-syrup/utils/System.h glucose-syrup-patched/utils/System.h +--- glucose-syrup/utils/System.h 2014-10-03 11:10:22.000000000 +0200 ++++ glucose-syrup-patched/utils/System.h 2018-04-21 16:58:22.950005391 +0200 @@ -60,8 +60,11 @@ static inline double Glucose::cpuTime(vo // Laurent: I know that this will not compile directly under Windows... sorry for that diff --git a/scripts/glucose_CMakeLists.txt b/scripts/glucose_CMakeLists.txt index 94165238d8a..38506152963 100644 --- a/scripts/glucose_CMakeLists.txt +++ b/scripts/glucose_CMakeLists.txt @@ -18,3 +18,5 @@ target_include_directories(glucose-condensed PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ) + +target_link_libraries(glucose-condensed util) From 07361b36666683b8683a52ac64b4597ab93d7d0e Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 21 Apr 2018 22:25:04 +0100 Subject: [PATCH 11/93] Bugfix: Java array symbols must have mode ID_java --- src/java_bytecode/java_bytecode_convert_class.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index 877252f5e12..62e1fd51fdc 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -740,6 +740,7 @@ void java_bytecode_convert_classt::add_array_types(symbol_tablet &symbol_table) symbol.base_name=symbol_type.get(ID_C_base_name); symbol.is_type=true; symbol.type = class_type; + symbol.mode = ID_java; symbol_table.add(symbol); // Also provide a clone method: From 696720ed866a91ae06edf164c66dfbbe5f03465a Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 21 Apr 2018 22:26:45 +0100 Subject: [PATCH 12/93] Bugfix: Java symbol types must have mode ID_java --- src/java_bytecode/java_bytecode_typecheck_type.cpp | 1 + src/java_bytecode/java_string_library_preprocess.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/java_bytecode/java_bytecode_typecheck_type.cpp b/src/java_bytecode/java_bytecode_typecheck_type.cpp index aa92d9333cf..79fb175db96 100644 --- a/src/java_bytecode/java_bytecode_typecheck_type.cpp +++ b/src/java_bytecode/java_bytecode_typecheck_type.cpp @@ -57,5 +57,6 @@ void java_bytecode_typecheckt::typecheck_type_symbol(symbolt &symbol) { assert(symbol.is_type); + symbol.mode = ID_java; typecheck_type(symbol.type); } diff --git a/src/java_bytecode/java_string_library_preprocess.cpp b/src/java_bytecode/java_string_library_preprocess.cpp index 009882d2dab..460398abbd9 100644 --- a/src/java_bytecode/java_string_library_preprocess.cpp +++ b/src/java_bytecode/java_string_library_preprocess.cpp @@ -247,6 +247,7 @@ void java_string_library_preprocesst::add_string_type( string_symbol->pretty_name=id2string(class_name); string_symbol->type=string_type; string_symbol->is_type=true; + string_symbol->mode = ID_java; } /// add a symbol in the table with static lifetime and name containing From 6bd897e353055ed30cddf17c287d39930a5ee479 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Sat, 31 Mar 2018 15:22:26 +0100 Subject: [PATCH 13/93] Add support for CaDiCaL CaDiCaL is Armin Biere's latest solver with a minimal IPASIR-compatible interface. In some initial experiments it considerable outperforms Minisat. --- scripts/cadical-patch | 10 +++ src/Makefile | 9 ++ src/common | 6 +- src/config.inc | 5 ++ src/solvers/Makefile | 12 ++- src/solvers/sat/satcheck.h | 12 +++ src/solvers/sat/satcheck_cadical.cpp | 129 +++++++++++++++++++++++++++ src/solvers/sat/satcheck_cadical.h | 43 +++++++++ 8 files changed, 223 insertions(+), 3 deletions(-) create mode 100644 scripts/cadical-patch create mode 100644 src/solvers/sat/satcheck_cadical.cpp create mode 100644 src/solvers/sat/satcheck_cadical.h diff --git a/scripts/cadical-patch b/scripts/cadical-patch new file mode 100644 index 00000000000..5baec02a370 --- /dev/null +++ b/scripts/cadical-patch @@ -0,0 +1,10 @@ +--- a/src/cadical.hpp 2018-03-10 14:22:11.000000000 +0000 ++++ b/src/cadical.hpp 2018-03-31 16:18:32.000000000 +0100 +@@ -141,6 +141,6 @@ + File * output (); // get access to internal 'output' file + }; + +-}; ++} + + #endif diff --git a/src/Makefile b/src/Makefile index 82141a0f317..d570dbb641a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -107,6 +107,15 @@ ipasir-build: ipasir-download $(MAKE) -C ../ipasir/sat/picosat961 libipasirpicosat961.a @(cd ../ipasir; ln -sf sat/picosat961/libipasirpicosat961.a libipasir.a) +cadical_release = rel-06w +cadical-download: + @echo "Downloading CaDiCaL $(cadical_release)" + @curl -L https://github.com/arminbiere/cadical/archive/$(cadical_release).tar.gz | tar xz + @rm -Rf ../cadical + @mv cadical-$(cadical_release) ../cadical + @(cd ../cadical; patch -p1 < ../scripts/cadical-patch) + @cd ../cadical && CXX=$(CXX) CXXFLAGS=-O3 ./configure --debug && make + doc : doxygen diff --git a/src/common b/src/common index ef872268350..81ede8836ab 100644 --- a/src/common +++ b/src/common @@ -159,7 +159,7 @@ else endif # select default solver to be minisat2 if no other is specified -ifeq ($(BOOLEFORCE)$(CHAFF)$(GLUCOSE)$(IPASIR)$(LINGELING)$(MINISAT)$(MINISAT2)$(PICOSAT),) +ifeq ($(BOOLEFORCE)$(CHAFF)$(GLUCOSE)$(IPASIR)$(LINGELING)$(MINISAT)$(MINISAT2)$(PICOSAT)$(CADICAL),) MINISAT2 = ../../minisat-2.2.1 endif @@ -195,6 +195,10 @@ ifneq ($(GLUCOSE),) CP_CXXFLAGS += -DHAVE_GLUCOSE endif +ifneq ($(CADICAL),) + CP_CXXFLAGS += -DHAVE_CADICAL +endif + first_target: all diff --git a/src/config.inc b/src/config.inc index 00d2bda6845..1bbaee22575 100644 --- a/src/config.inc +++ b/src/config.inc @@ -24,6 +24,7 @@ endif #MINISAT2 = ../../minisat-2.2.1 #IPASIR = ../../ipasir #GLUCOSE = ../../glucose-syrup +#CADICAL = ../../cadical # Extra library for SAT solver. This should link to the archive file to be used # when linking against an IPASIR solver. @@ -57,6 +58,10 @@ ifneq ($(GLUCOSE),) CP_CXXFLAGS += -DSATCHECK_GLUCOSE endif +ifneq ($(CADICAL),) + CP_CXXFLAGS += -DSATCHECK_CADICAL +endif + # Signing identity for MacOS Gatekeeper OSX_IDENTITY="Developer ID Application: Daniel Kroening" diff --git a/src/solvers/Makefile b/src/solvers/Makefile index 3d1a572eb36..2256e0ee977 100644 --- a/src/solvers/Makefile +++ b/src/solvers/Makefile @@ -67,6 +67,13 @@ ifneq ($(LINGELING),) CP_CXXFLAGS += -DHAVE_LINGELING endif +ifneq ($(CADICAL),) + CADICAL_SRC=sat/satcheck_cadical.cpp + CADICAL_INCLUDE=-I $(CADICAL)/src + CADICAL_LIB=$(CADICAL)/build/libcadical$(LIBEXT) + CP_CXXFLAGS += -DHAVE_CADICAL +endif + SRC = $(BOOLEFORCE_SRC) \ $(CHAFF_SRC) \ $(CUDD_SRC) \ @@ -77,6 +84,7 @@ SRC = $(BOOLEFORCE_SRC) \ $(MINISAT_SRC) \ $(PICOSAT_SRC) \ $(SQUOLEM2_SRC) \ + $(CADICAL_SRC) \ cvc/cvc_conv.cpp \ cvc/cvc_dec.cpp \ flattening/arrays.cpp \ @@ -194,7 +202,7 @@ INCLUDES += -I .. \ $(CHAFF_INCLUDE) $(BOOLEFORCE_INCLUDE) $(MINISAT_INCLUDE) $(MINISAT2_INCLUDE) \ $(IPASIR_INCLUDE) \ $(SQUOLEM2_INC) $(CUDD_INCLUDE) $(GLUCOSE_INCLUDE) \ - $(PICOSAT_INCLUDE) $(LINGELING_INCLUDE) + $(PICOSAT_INCLUDE) $(LINGELING_INCLUDE) $(CADICAL_INCLUDE) CLEANFILES += solvers$(LIBEXT) \ smt2_solver$(EXEEXT) smt2/smt2_solver$(OBJEXT) smt2/smt2_solver$(DEPEXT) @@ -211,7 +219,7 @@ endif SOLVER_LIB = $(CHAFF_LIB) $(BOOLEFORCE_LIB) $(MINISAT_LIB) \ $(MINISAT2_LIB) $(SQUOLEM2_LIB) $(CUDD_LIB) \ - $(PICOSAT_LIB) $(LINGELING_LIB) $(GLUCOSE_LIB) + $(PICOSAT_LIB) $(LINGELING_LIB) $(GLUCOSE_LIB) $(CADICAL_LIB) ############################################################################### diff --git a/src/solvers/sat/satcheck.h b/src/solvers/sat/satcheck.h index 6896be55da4..c7175fa414c 100644 --- a/src/solvers/sat/satcheck.h +++ b/src/solvers/sat/satcheck.h @@ -21,6 +21,7 @@ Author: Daniel Kroening, kroening@kroening.com // #define SATCHECK_BOOLEFORCE // #define SATCHECK_PICOSAT // #define SATCHECK_LINGELING +// #define SATCHECK_CADICAL #if defined(HAVE_IPASIR) && !defined(SATCHECK_IPASIR) #define SATCHECK_IPASIR @@ -54,6 +55,10 @@ Author: Daniel Kroening, kroening@kroening.com #define SATCHECK_LINGELING #endif +#if defined(HAVE_CADICAL) && !defined(SATCHECK_CADICAL) +#define SATCHECK_CADICAL +#endif + #if defined SATCHECK_ZCHAFF #include "satcheck_zchaff.h" @@ -110,6 +115,13 @@ typedef satcheck_lingelingt satcheck_no_simplifiert; typedef satcheck_glucose_simplifiert satcheckt; typedef satcheck_glucose_no_simplifiert satcheck_no_simplifiert; +#elif defined SATCHECK_CADICAL + +#include "satcheck_cadical.h" + +typedef satcheck_cadicalt satcheckt; +typedef satcheck_cadicalt satcheck_no_simplifiert; + #endif #endif // CPROVER_SOLVERS_SAT_SATCHECK_H diff --git a/src/solvers/sat/satcheck_cadical.cpp b/src/solvers/sat/satcheck_cadical.cpp new file mode 100644 index 00000000000..a92a815ffc7 --- /dev/null +++ b/src/solvers/sat/satcheck_cadical.cpp @@ -0,0 +1,129 @@ +/*******************************************************************\ + +Module: + +Author: Michael Tautschnig + +\*******************************************************************/ + +#include "satcheck_cadical.h" + +#include +#include + +#ifdef HAVE_CADICAL + +#include + +tvt satcheck_cadicalt::l_get(literalt a) const +{ + if(a.is_constant()) + return tvt(a.sign()); + + tvt result; + + if(a.var_no() > static_cast(solver->max())) + return tvt(tvt::tv_enumt::TV_UNKNOWN); + + const int val = solver->val(a.dimacs()); + if(val>0) + result = tvt(true); + else if(val<0) + result = tvt(false); + else + return tvt(tvt::tv_enumt::TV_UNKNOWN); + + return result; +} + +const std::string satcheck_cadicalt::solver_text() +{ + return std::string("CaDiCaL ") + solver->version(); +} + +void satcheck_cadicalt::lcnf(const bvt &bv) +{ + for(const auto &lit : bv) + { + if(lit.is_true()) + return; + else if(!lit.is_false()) + INVARIANT(lit.var_no() < no_variables(), "reject out of bound variables"); + } + + for(const auto &lit : bv) + { + if(!lit.is_false()) + { + // add literal with correct sign + solver->add(lit.dimacs()); + } + } + solver->add(0); // terminate clause + + clause_counter++; +} + +propt::resultt satcheck_cadicalt::prop_solve() +{ + INVARIANT(status != statust::ERROR, "there cannot be an error"); + + messaget::status() << (no_variables() - 1) << " variables, " << clause_counter + << " clauses" << eom; + + if(status == statust::UNSAT) + { + messaget::status() << "SAT checker inconsistent: instance is UNSATISFIABLE" + << eom; + } + else + { + switch(solver->solve()) + { + case 10: + messaget::status() << "SAT checker: instance is SATISFIABLE" << eom; + status = statust::SAT; + return resultt::P_SATISFIABLE; + case 20: + messaget::status() << "SAT checker: instance is UNSATISFIABLE" << eom; + break; + default: + messaget::status() << "SAT checker: solving returned without solution" + << eom; + throw "solving inside CaDiCaL SAT solver has been interrupted"; + } + } + + status = statust::UNSAT; + return resultt::P_UNSATISFIABLE; +} + +void satcheck_cadicalt::set_assignment(literalt a, bool value) +{ + INVARIANT(!a.is_constant(), "cannot set an assignment for a constant"); + INVARIANT(false, "method not supported"); +} + +satcheck_cadicalt::satcheck_cadicalt() : + solver(new CaDiCaL::Solver()) +{ + solver->set("quiet", 1); +} + +satcheck_cadicalt::~satcheck_cadicalt() +{ + delete solver; +} + +void satcheck_cadicalt::set_assumptions(const bvt &bv) +{ + INVARIANT(false, "method not supported"); +} + +bool satcheck_cadicalt::is_in_conflict(literalt a) const +{ + INVARIANT(false, "method not supported"); + return false; +} + +#endif diff --git a/src/solvers/sat/satcheck_cadical.h b/src/solvers/sat/satcheck_cadical.h new file mode 100644 index 00000000000..763b2e3f150 --- /dev/null +++ b/src/solvers/sat/satcheck_cadical.h @@ -0,0 +1,43 @@ +/*******************************************************************\ + +Module: + +Author: Michael Tautschnig + +\*******************************************************************/ + + +#ifndef CPROVER_SOLVERS_SAT_SATCHECK_CADICAL_H +#define CPROVER_SOLVERS_SAT_SATCHECK_CADICAL_H + +#include "cnf.h" + +namespace CaDiCaL // NOLINT(readability/namespace) +{ + class Solver; // NOLINT(readability/identifiers) +} + +class satcheck_cadicalt:public cnf_solvert +{ +public: + satcheck_cadicalt(); + virtual ~satcheck_cadicalt(); + + virtual const std::string solver_text() override; + virtual resultt prop_solve() override; + virtual tvt l_get(literalt a) const override; + + virtual void lcnf(const bvt &bv) override; + virtual void set_assignment(literalt a, bool value) override; + + virtual void set_assumptions(const bvt &_assumptions) override; + virtual bool has_set_assumptions() const override { return false; } + virtual bool has_is_in_conflict() const override { return false; } + virtual bool is_in_conflict(literalt a) const override; + +protected: + // NOLINTNEXTLINE(readability/identifiers) + CaDiCaL::Solver * solver; +}; + +#endif // CPROVER_SOLVERS_SAT_SATCHECK_CADICAL_H From 515ea22f5d4e89aecd1f346eee4810beddb8972e Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Fri, 13 Apr 2018 07:19:47 +0100 Subject: [PATCH 14/93] Correct bound in test with long string To make the solver abort the length has to be strictly greater than 2^26. --- regression/jbmc-strings/long_string/Test.class | Bin 985 -> 985 bytes regression/jbmc-strings/long_string/Test.java | 4 +++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/regression/jbmc-strings/long_string/Test.class b/regression/jbmc-strings/long_string/Test.class index de6b488b03b1fb4093bf83ec7dc0a8eec3ef3a01..9442a3c1cf466c5158a588f53da0901a688f5f87 100644 GIT binary patch delta 39 scmcb~ev^HJ4m0E8$-2yzqRI>s3@Qwg45~m<4M=J-7&B;1u4aw{0IkjkRsaA1 delta 39 tcmcb~ev^HJ4m0DT$-2yzqKXU>3`z`=49W~DK&Z-~&S1=-F}a#K4gjqC2T1?` diff --git a/regression/jbmc-strings/long_string/Test.java b/regression/jbmc-strings/long_string/Test.java index 63b0d69babc..5decee61931 100644 --- a/regression/jbmc-strings/long_string/Test.java +++ b/regression/jbmc-strings/long_string/Test.java @@ -30,7 +30,9 @@ public static void checkAbort(String s, String t) { String u = s.concat(t); // Filter out - if(u.length() < 67_108_864) + // 67_108_864 corresponds to the maximum length for which the solver + // will concretize the string. + if(u.length() <= 67_108_864) return; if(CProverString.charAt(u, 2_000_000) != 'b') return; From 8c2f4c14b52c4d0585058c5c00978db858291f57 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Thu, 1 Mar 2018 13:40:46 +0000 Subject: [PATCH 15/93] Remove unnecessary replace_expr This is already done in add_lemma. --- src/solvers/refinement/string_refinement.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index c2685dc6202..dd384135af3 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -723,11 +723,8 @@ decision_proceduret::resultt string_refinementt::dec_solve() generator.fresh_symbol("not_contains_witness", witness_type); } - for(exprt lemma : generator.get_lemmas()) - { - symbol_resolve.replace_expr(lemma); + for(const exprt &lemma : generator.get_lemmas()) add_lemma(lemma); - } // Initial try without index set const auto get = [this](const exprt &expr) { return this->get(expr); }; From d83fa5a08f3c7b5586a7360de963befa8bc97e40 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 26 Feb 2018 08:28:32 +0000 Subject: [PATCH 16/93] Use boolbvt for getting counter examples We use this counter examples in the string solver but the formula given there don't use arrays so it is enough to use boolbvt. --- src/solvers/refinement/string_refinement.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index dd384135af3..2356acc6ddf 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -2168,14 +2168,7 @@ static optionalt find_counter_example( const symbol_exprt &var) { satcheck_no_simplifiert sat_check; - bv_refinementt::infot info; - info.ns=&ns; - info.prop=&sat_check; - info.refine_arithmetic=true; - info.refine_arrays=true; - info.max_node_refinement=5; - info.ui=ui; - bv_refinementt solver(info); + boolbvt solver(ns, sat_check); solver << axiom; if(solver()==decision_proceduret::resultt::D_SATISFIABLE) From cfaa6505619aa5980436e2bf8e02a2a1ad5795aa Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Wed, 7 Feb 2018 08:54:10 +0000 Subject: [PATCH 17/93] Use string-max-length as default max input-length Having input string longer than string-max-length does not make sense as the solver will not know how to analyse them. So when string-max-input-length is not specified we can use string-max-length instead. --- src/java_bytecode/java_bytecode_language.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index a139b75c613..967113657ce 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -55,6 +55,10 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd) if(cmd.isset("string-max-input-length")) object_factory_parameters.max_nondet_string_length= std::stoi(cmd.get_value("string-max-input-length")); + else if(cmd.isset("string-max-length")) + object_factory_parameters.max_nondet_string_length = + std::stoi(cmd.get_value("string-max-length")); + object_factory_parameters.string_printable = cmd.isset("string-printable"); if(cmd.isset("java-max-vla-length")) max_user_array_length=std::stoi(cmd.get_value("java-max-vla-length")); From 7c4d8f7b209ab3d8c005d51948cf05f3488dfdf1 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Thu, 12 Apr 2018 19:09:01 +0100 Subject: [PATCH 18/93] Make get_array return nil for long strings Instead of aborting the program when the string is too long, we consider this happened because of some invalid object, and return nil as a model of the array. Access to this invalid object is prevented by other part of the code and should not occur in the trace. --- .../jbmc-strings/long_string/test_abort.desc | 9 +++++---- src/solvers/refinement/string_refinement.cpp | 17 +++++++++++------ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/regression/jbmc-strings/long_string/test_abort.desc b/regression/jbmc-strings/long_string/test_abort.desc index 22074e1ed1e..8daa50acd1a 100644 --- a/regression/jbmc-strings/long_string/test_abort.desc +++ b/regression/jbmc-strings/long_string/test_abort.desc @@ -1,9 +1,10 @@ CORE Test.class ---refine-strings --function Test.checkAbort -^EXIT=6$ +--refine-strings --function Test.checkAbort --trace +^EXIT=10$ ^SIGNAL=0$ +dynamic_object[0-9]*=\(assignment removed\) -- -- -This tests should abort, because concretizing a string of the required -length may take to much memory. +This tests that the object does not appear in the trace, because concretizing +a string of the required length may take too much memory. diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index 2356acc6ddf..e358cade7b2 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -933,12 +933,17 @@ static optionalt get_array( if(n > MAX_CONCRETE_STRING_SIZE) { - stream << "(sr::get_array) long string (size=" << n << ")" << eom; - std::ostringstream msg; - msg << "consider reducing string-max-input-length so that no string " - << "exceeds " << MAX_CONCRETE_STRING_SIZE << " in length and make sure" - << " all functions returning strings are available in the classpath"; - throw string_refinement_invariantt(msg.str()); + stream << "(sr::get_array) long string (size " << format(arr.length()) + << " = " << n << ") " << format(arr) << eom; + stream << "(sr::get_array) consider reducing string-max-input-length so " + "that no string exceeds " + << MAX_CONCRETE_STRING_SIZE + << " in length and " + "make sure all functions returning strings are loaded" + << eom; + stream << "(sr::get_array) this can also happen on invalid object access" + << eom; + return nil_exprt(); } if( From 97c1149940cac377cd84f95c7edd571179e5efea Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Thu, 12 Apr 2018 19:03:00 +0100 Subject: [PATCH 19/93] Weaken invariant for nil exprt as model of array nil_exprt happens when the underlying solver has no formula talking about the array --- src/solvers/refinement/string_refinement.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index e358cade7b2..3c081bf1adc 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -1123,9 +1123,6 @@ static exprt substitute_array_access( const bool left_propagate) { const exprt &array = index_expr.array(); - - if(array.id() == ID_symbol) - return index_expr; if(auto array_of = expr_try_dynamic_cast(array)) return array_of->op(); if(auto array_with = expr_try_dynamic_cast(array)) @@ -1138,7 +1135,12 @@ static exprt substitute_array_access( return substitute_array_access( *if_expr, index_expr.index(), symbol_generator, left_propagate); - UNREACHABLE; + INVARIANT( + array.is_nil() || array.id() == ID_symbol, + std::string( + "in case the array is unknown, it should be a symbol or nil, id: ") + + id2string(array.id())); + return index_expr; } /// Auxiliary function for substitute_array_access @@ -2121,9 +2123,11 @@ exprt string_refinementt::get(const exprt &expr) const } INVARIANT( - array.id() == ID_symbol, - "apart from symbols, array valuations can be interpreted as sparse " - "arrays"); + array.is_nil() || array.id() == ID_symbol, + std::string( + "apart from symbols, array valuations can be interpreted as " + "sparse arrays, id: ") + + id2string(array.id())); return index_exprt(array, index); } From 925c63948781cce111758403e7c93f0093828d34 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Thu, 12 Apr 2018 18:54:45 +0100 Subject: [PATCH 20/93] Assign 0 to string length for null Java String Although we should not reach this code if rhs is null, the association `pointer -> length` is added to the solver anyway, so we have to make sure the length of the string_exprt is set to something reasonable. --- src/java_bytecode/java_string_library_preprocess.cpp | 11 ++++++++--- .../convert_exprt_to_string_exprt.cpp | 5 +++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/java_bytecode/java_string_library_preprocess.cpp b/src/java_bytecode/java_string_library_preprocess.cpp index 460398abbd9..3c73c3e8ae6 100644 --- a/src/java_bytecode/java_string_library_preprocess.cpp +++ b/src/java_bytecode/java_string_library_preprocess.cpp @@ -878,7 +878,7 @@ codet java_string_library_preprocesst::code_assign_string_expr_to_java_string( /// \param symbol_table: symbol table /// \param [out] code: code block that gets appended the following code: /// ~~~~~~~~~~~~~~~~~~~~~~ -/// lhs.length=rhs->length +/// lhs.length = rhs==null ? 0 : rhs->length /// lhs.data=rhs->data /// ~~~~~~~~~~~~~~~~~~~~~~ void java_string_library_preprocesst::code_assign_java_string_to_string_expr( @@ -899,8 +899,13 @@ void java_string_library_preprocesst::code_assign_java_string_to_string_expr( const dereference_exprt deref = checked_dereference(rhs, deref_type); - // Fields of the string object - const exprt rhs_length = get_length(deref, symbol_table); + // Although we should not reach this code if rhs is null, the association + // `pointer -> length` is added to the solver anyway, so we have to make sure + // the length is set to something reasonable. + const auto rhs_length = if_exprt( + equal_exprt(rhs, null_pointer_exprt(to_pointer_type(rhs.type()))), + from_integer(0, lhs.length().type()), + get_length(deref, symbol_table)); // Assignments code.add(code_assignt(lhs.length(), rhs_length), loc); diff --git a/unit/java_bytecode/java_string_library_preprocess/convert_exprt_to_string_exprt.cpp b/unit/java_bytecode/java_string_library_preprocess/convert_exprt_to_string_exprt.cpp index b292e445ae2..fb65105afbb 100644 --- a/unit/java_bytecode/java_string_library_preprocess/convert_exprt_to_string_exprt.cpp +++ b/unit/java_bytecode/java_string_library_preprocess/convert_exprt_to_string_exprt.cpp @@ -68,10 +68,11 @@ TEST_CASE("Convert exprt to string exprt") std::regex_replace(line, spaces, " "), numbers, "")); } - const std::vector reference_code = { // NOLINT + const std::vector reference_code = { + // NOLINT "char *cprover_string_content;", "int cprover_string_length;", - "cprover_string_length = a->length;", + "cprover_string_length = a == null ? 0 : a->length;", "cprover_string_content = a->data;"}; for(std::size_t i = 0; From 24d756233a7fd4edecdd32be4a75056624d13269 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 19 Feb 2018 15:43:15 +0000 Subject: [PATCH 21/93] Get rid of default axioms for strings These default axioms where too strict and where applied even for strings that may never be created in the actual program. This could for instance lead to problematic contradiction for a Java object which could be casted either to a string or an int: the axiom added there would apply both on the string and on the integer. --- .../refinement/string_constraint_generator.h | 1 - .../string_constraint_generator_main.cpp | 29 +++---------------- 2 files changed, 4 insertions(+), 26 deletions(-) diff --git a/src/solvers/refinement/string_constraint_generator.h b/src/solvers/refinement/string_constraint_generator.h index 0beb04b766f..1102011302a 100644 --- a/src/solvers/refinement/string_constraint_generator.h +++ b/src/solvers/refinement/string_constraint_generator.h @@ -184,7 +184,6 @@ class string_constraint_generatort final array_string_exprt char_array_of_pointer(const exprt &pointer, const exprt &length); - void add_default_axioms(const array_string_exprt &s); exprt axiom_for_is_positive_index(const exprt &x); void add_constraint_on_characters( diff --git a/src/solvers/refinement/string_constraint_generator_main.cpp b/src/solvers/refinement/string_constraint_generator_main.cpp index 72cb6a97120..db60ef1e786 100644 --- a/src/solvers/refinement/string_constraint_generator_main.cpp +++ b/src/solvers/refinement/string_constraint_generator_main.cpp @@ -172,7 +172,6 @@ array_string_exprt string_constraint_generatort::fresh_string( symbol_exprt content = fresh_symbol("string_content", array_type); array_string_exprt str = to_array_string_expr(content); created_strings.insert(str); - add_default_axioms(str); return str; } @@ -279,7 +278,7 @@ exprt string_constraint_generatort::associate_array_to_pointer( const exprt &pointer_expr = f.arguments()[1]; array_pool.insert(pointer_expr, array_expr); - add_default_axioms(to_array_string_expr(array_expr)); + created_strings.emplace(to_array_string_expr(array_expr)); return from_integer(0, f.type()); } @@ -319,27 +318,6 @@ void string_constraint_generatort::clear_constraints() not_contains_constraints.clear(); } -/// adds standard axioms about the length of the string and its content: * its -/// length should be positive * it should not exceed max_string_length * if -/// force_printable_characters is true then all characters should belong to the -/// range of ASCII characters between ' ' and '~' -/// \param s: a string expression -/// \return a string expression that is linked to the argument through axioms -/// that are added to the list -void string_constraint_generatort::add_default_axioms( - const array_string_exprt &s) -{ - // If `s` was already added we do nothing. - if(!created_strings.insert(s).second) - return; - - const exprt index_zero = from_integer(0, s.length().type()); - lemmas.push_back(s.axiom_for_length_ge(index_zero)); - - if(max_string_length!=std::numeric_limits::max()) - lemmas.push_back(s.axiom_for_length_le(max_string_length)); -} - /// Add constraint on characters of a string. /// /// This constraint is @@ -409,13 +387,14 @@ array_string_exprt array_poolt::find(const exprt &pointer, const exprt &length) } /// Adds creates a new array if it does not already exists -/// \todo This should be replaced by associate_char_array_to_char_pointer +/// \todo This should be replaced +/// by array_poolt.make_char_array_for_char_pointer array_string_exprt string_constraint_generatort::char_array_of_pointer( const exprt &pointer, const exprt &length) { const array_string_exprt array = array_pool.find(pointer, length); - add_default_axioms(array); + created_strings.insert(array); return array; } From 381f45bbeefd11f07a58e122eeee73e78ffe1b7a Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 16 Apr 2018 08:21:37 +0100 Subject: [PATCH 22/93] Make char_array_of_pointer return a reference --- src/solvers/refinement/string_constraint_generator.h | 2 +- src/solvers/refinement/string_constraint_generator_main.cpp | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/solvers/refinement/string_constraint_generator.h b/src/solvers/refinement/string_constraint_generator.h index 1102011302a..d9d69abf325 100644 --- a/src/solvers/refinement/string_constraint_generator.h +++ b/src/solvers/refinement/string_constraint_generator.h @@ -181,7 +181,7 @@ class string_constraint_generatort final static constant_exprt constant_char(int i, const typet &char_type); - array_string_exprt + const array_string_exprt & char_array_of_pointer(const exprt &pointer, const exprt &length); exprt axiom_for_is_positive_index(const exprt &x); diff --git a/src/solvers/refinement/string_constraint_generator_main.cpp b/src/solvers/refinement/string_constraint_generator_main.cpp index db60ef1e786..41f7cf193d7 100644 --- a/src/solvers/refinement/string_constraint_generator_main.cpp +++ b/src/solvers/refinement/string_constraint_generator_main.cpp @@ -389,13 +389,11 @@ array_string_exprt array_poolt::find(const exprt &pointer, const exprt &length) /// Adds creates a new array if it does not already exists /// \todo This should be replaced /// by array_poolt.make_char_array_for_char_pointer -array_string_exprt string_constraint_generatort::char_array_of_pointer( +const array_string_exprt &string_constraint_generatort::char_array_of_pointer( const exprt &pointer, const exprt &length) { - const array_string_exprt array = array_pool.find(pointer, length); - created_strings.insert(array); - return array; + return *created_strings.insert(array_pool.find(pointer, length)).first; } array_string_exprt array_poolt::find(const refined_string_exprt &str) From 3c35e3ffd873c8b8baa4043329f1e738f14179de Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 19 Feb 2018 15:45:44 +0000 Subject: [PATCH 23/93] Get rid of string_max_length field In constraint generator, this was used for adding default axioms but is no longer used. --- src/cbmc/cbmc_solvers.cpp | 2 +- .../refinement/string_constraint_generator.h | 10 +------- .../string_constraint_generator_main.cpp | 6 ++--- src/solvers/refinement/string_refinement.cpp | 23 +++++++++++-------- src/solvers/refinement/string_refinement.h | 3 ++- .../instantiate_not_contains.cpp | 18 +++++---------- 6 files changed, 25 insertions(+), 37 deletions(-) diff --git a/src/cbmc/cbmc_solvers.cpp b/src/cbmc/cbmc_solvers.cpp index 557bf1ca3b7..ed5787af6d3 100644 --- a/src/cbmc/cbmc_solvers.cpp +++ b/src/cbmc/cbmc_solvers.cpp @@ -177,7 +177,7 @@ std::unique_ptr cbmc_solverst::get_string_refinement() info.refinement_bound=DEFAULT_MAX_NB_REFINEMENT; info.ui=ui; if(options.get_bool_option("string-max-length")) - info.string_max_length=options.get_signed_int_option("string-max-length"); + info.max_string_length = options.get_signed_int_option("string-max-length"); info.trace=options.get_bool_option("trace"); if(options.get_bool_option("max-node-refinement")) info.max_node_refinement= diff --git a/src/solvers/refinement/string_constraint_generator.h b/src/solvers/refinement/string_constraint_generator.h index d9d69abf325..5a921d11adc 100644 --- a/src/solvers/refinement/string_constraint_generator.h +++ b/src/solvers/refinement/string_constraint_generator.h @@ -94,14 +94,7 @@ class string_constraint_generatort final // Used by format function class format_specifiert; - /// Arguments pack for the string_constraint_generator constructor - struct infot - { - /// Max length of non-deterministic strings - size_t string_max_length=std::numeric_limits::max(); - }; - - string_constraint_generatort(const infot& info, const namespacet& ns); + explicit string_constraint_generatort(const namespacet &ns); /// Axioms are of three kinds: universally quantified string constraint, /// not contains string constraints and simple formulas. @@ -401,7 +394,6 @@ class string_constraint_generatort final // MEMBERS public: - const size_t max_string_length; // Used to store information about witnesses for not_contains constraints std::map witness; private: diff --git a/src/solvers/refinement/string_constraint_generator_main.cpp b/src/solvers/refinement/string_constraint_generator_main.cpp index 41f7cf193d7..3b3dc66c846 100644 --- a/src/solvers/refinement/string_constraint_generator_main.cpp +++ b/src/solvers/refinement/string_constraint_generator_main.cpp @@ -28,10 +28,8 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com #include #include -string_constraint_generatort::string_constraint_generatort( - const string_constraint_generatort::infot &info, - const namespacet &ns) - : array_pool(fresh_symbol), max_string_length(info.string_max_length), ns(ns) +string_constraint_generatort::string_constraint_generatort(const namespacet &ns) + : array_pool(fresh_symbol), ns(ns) { } diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index 3c081bf1adc..52539307f0f 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -166,11 +166,14 @@ static bool validate(const string_refinementt::infot &info) return true; } -string_refinementt::string_refinementt(const infot &info, bool): - supert(info), - config_(info), - loop_bound_(info.refinement_bound), - generator(info, *info.ns) { } +string_refinementt::string_refinementt(const infot &info, bool) + : supert(info), + config_(info), + loop_bound_(info.refinement_bound), + max_string_length(info.max_string_length), + generator(*info.ns) +{ +} string_refinementt::string_refinementt(const infot &info): string_refinementt(info, validate(info)) { } @@ -734,13 +737,13 @@ decision_proceduret::resultt string_refinementt::dec_solve() { bool satisfied; std::vector counter_examples; - std::tie(satisfied, counter_examples)=check_axioms( + std::tie(satisfied, counter_examples) = check_axioms( axioms, generator, get, debug(), ns, - generator.max_string_length, + max_string_length, config_.use_counter_example, supert::config_.ui, symbol_resolve); @@ -778,13 +781,13 @@ decision_proceduret::resultt string_refinementt::dec_solve() { bool satisfied; std::vector counter_examples; - std::tie(satisfied, counter_examples)=check_axioms( + std::tie(satisfied, counter_examples) = check_axioms( axioms, generator, get, debug(), ns, - generator.max_string_length, + max_string_length, config_.use_counter_example, supert::config_.ui, symbol_resolve); @@ -2143,7 +2146,7 @@ exprt string_refinementt::get(const exprt &expr) const if( const auto arr_model_opt = - get_array(super_get, ns, generator.max_string_length, debug(), arr)) + get_array(super_get, ns, max_string_length, debug(), arr)) return *arr_model_opt; if(generator.get_created_strings().count(arr)) diff --git a/src/solvers/refinement/string_refinement.h b/src/solvers/refinement/string_refinement.h index 0fd5dbc8f5a..f33c1bcf0b0 100644 --- a/src/solvers/refinement/string_refinement.h +++ b/src/solvers/refinement/string_refinement.h @@ -43,11 +43,11 @@ class string_refinementt final: public bv_refinementt /// Concretize strings after solver is finished bool trace=false; bool use_counter_example=true; + std::size_t max_string_length; }; public: /// string_refinementt constructor arguments struct infot : public bv_refinementt::infot, - public string_constraint_generatort::infot, public configt { }; @@ -69,6 +69,7 @@ class string_refinementt final: public bv_refinementt const configt config_; std::size_t loop_bound_; + std::size_t max_string_length; string_constraint_generatort generator; // Simple constraints that have been given to the solver diff --git a/unit/solvers/refinement/string_constraint_instantiation/instantiate_not_contains.cpp b/unit/solvers/refinement/string_constraint_instantiation/instantiate_not_contains.cpp index 3556cc26915..db6e28193c4 100644 --- a/unit/solvers/refinement/string_constraint_instantiation/instantiate_not_contains.cpp +++ b/unit/solvers/refinement/string_constraint_instantiation/instantiate_not_contains.cpp @@ -195,8 +195,7 @@ SCENARIO("instantiate_not_contains", // Generating the corresponding axioms and simplifying, recording info symbol_tablet symtab; const namespacet empty_ns(symtab); - string_constraint_generatort::infot info; - string_constraint_generatort generator(info, ns); + string_constraint_generatort generator(ns); exprt res=generator.add_axioms_for_function_application(func); std::string axioms; std::vector nc_axioms; @@ -297,8 +296,7 @@ SCENARIO("instantiate_not_contains", // Create witness for axiom symbol_tablet symtab; const namespacet empty_ns(symtab); - string_constraint_generatort::infot info; - string_constraint_generatort generator(info, ns); + string_constraint_generatort generator(ns); generator.witness[vacuous]= generator.fresh_symbol("w", t.witness_type()); @@ -353,8 +351,7 @@ SCENARIO("instantiate_not_contains", // Create witness for axiom symbol_tablet symtab; const namespacet ns(symtab); - string_constraint_generatort::infot info; - string_constraint_generatort generator(info, ns); + string_constraint_generatort generator(ns); generator.witness[trivial]= generator.fresh_symbol("w", t.witness_type()); @@ -410,8 +407,7 @@ SCENARIO("instantiate_not_contains", // Create witness for axiom symbol_tablet symtab; const namespacet empty_ns(symtab); - string_constraint_generatort::infot info; - string_constraint_generatort generator(info, ns); + string_constraint_generatort generator(ns); generator.witness[trivial]= generator.fresh_symbol("w", t.witness_type()); @@ -470,8 +466,7 @@ SCENARIO("instantiate_not_contains", symbol_tablet symtab; const namespacet empty_ns(symtab); - string_constraint_generatort::infot info; - string_constraint_generatort generator(info, ns); + string_constraint_generatort generator(ns); generator.witness[trivial]= generator.fresh_symbol("w", t.witness_type()); @@ -527,8 +522,7 @@ SCENARIO("instantiate_not_contains", // Create witness for axiom symbol_tablet symtab; const namespacet empty_ns(symtab); - string_constraint_generatort::infot info; - string_constraint_generatort generator(info, ns); + string_constraint_generatort generator(ns); generator.witness[trivial]= generator.fresh_symbol("w", t.witness_type()); From 985ac776e5bf400df391668093b9df277c43854d Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Thu, 22 Feb 2018 12:13:48 +0000 Subject: [PATCH 24/93] Add test for generics array and strings This adds an int greater than string-max-length in a generic array. This is to check that TG-2138 is fixed. Before the issue was solved setting the array to 101 was in contradiction with default axioms added by the string solver. --- .../IntegerTests.class | Bin 0 -> 834 bytes .../IntegerTests.java | 44 ++++++++++++++++++ .../max-length-generic-array/MyGenSet.class | Bin 0 -> 501 bytes .../max-length-generic-array/MySet.class | Bin 0 -> 446 bytes .../max-length-generic-array/test.desc | 19 ++++++++ .../max-length-generic-array/test_gen.desc | 20 ++++++++ 6 files changed, 83 insertions(+) create mode 100644 regression/jbmc-strings/max-length-generic-array/IntegerTests.class create mode 100644 regression/jbmc-strings/max-length-generic-array/IntegerTests.java create mode 100644 regression/jbmc-strings/max-length-generic-array/MyGenSet.class create mode 100644 regression/jbmc-strings/max-length-generic-array/MySet.class create mode 100644 regression/jbmc-strings/max-length-generic-array/test.desc create mode 100644 regression/jbmc-strings/max-length-generic-array/test_gen.desc diff --git a/regression/jbmc-strings/max-length-generic-array/IntegerTests.class b/regression/jbmc-strings/max-length-generic-array/IntegerTests.class new file mode 100644 index 0000000000000000000000000000000000000000..6120bff5bb6f256912ddb4120be2d604bb633a6e GIT binary patch literal 834 zcmaKq&2G~`6ot=?V^3_{Hlb~x^p6%=>;w}2c10{e0#!=rB2}e^)g(+SmtZ5usgy_I zEsBI_1rlP1#4{npozx~~gBLS*?s(33&z<@C`^z@~kMYRCES3dU92Br@^ROzg=3pH+ zb!NlCCT#hUXs;iqE4riZIs-LiK9&uBYOC*&A@i zP1G=Hk6)^=qY{GWwNB)zYz}02+}sTlb*$nYKbLzJMFS#&#eMZ6(4b1Hw$Hp_LqlB5p-d=cbQeBqgoW2RTvmcW-NjwpbJ0Lk;J#iw zAeikj!}P&5z4MU$UBCN}a@s_#*Ujrqn_JC`WEj7T4b1Sf(4PUmPLz49@M@K3 z;@Pa7gFbRVxXPn7N%F;D9t#}nUlkuM@Z6~VfJtXxQ8+w@(W-w!@jFbTtS(@6>b1`h zA5bb@pmb*Fflm}BnpKz_7g^inQY@@MaQ{nKlZc!svKVXi|nPydWN(a>1gDY e9MAn9&t;OfK8q!`z0Jm_ymf)=Y;I{%;*CH4c&lXq literal 0 HcmV?d00001 diff --git a/regression/jbmc-strings/max-length-generic-array/IntegerTests.java b/regression/jbmc-strings/max-length-generic-array/IntegerTests.java new file mode 100644 index 00000000000..c57b3e19be8 --- /dev/null +++ b/regression/jbmc-strings/max-length-generic-array/IntegerTests.java @@ -0,0 +1,44 @@ +public class IntegerTests { + + public static Boolean testMyGenSet(Integer key) { + if (key == null) return null; + MyGenSet ms = new MyGenSet<>(); + ms.array[0] = 101; + if (ms.contains(key)) return true; + return false; + } + + public static Boolean testMySet(Integer key) { + if (key == null) return null; + MySet ms = new MySet(); + ms.array[0] = 101; + if (ms.contains(key)) return true; + return false; + } + +} + +class MyGenSet { + E[] array; + @SuppressWarnings("unchecked") + MyGenSet() { + array = (E[]) new Object[1]; + } + boolean contains(E o) { + if (o.equals(array[0])) + return true; + return false; + } +} + +class MySet { + Integer[] array; + MySet() { + array = new Integer[1]; + } + boolean contains(Integer o) { + if (o.equals(array[0])) + return true; + return false; + } +} diff --git a/regression/jbmc-strings/max-length-generic-array/MyGenSet.class b/regression/jbmc-strings/max-length-generic-array/MyGenSet.class new file mode 100644 index 0000000000000000000000000000000000000000..e92e43fee856008bdc97ae12d7bab364c7cd6c44 GIT binary patch literal 501 zcmZWl%TB^T6g|_Hr-c>~1w`YrU?Rr2Lc+$NF#%naxRBLQC!~l)`!L~C{0BBBJ`xj+ zYd^|(M_CwI%$HM^VP51j-CC?)!YokneX!{EpYh z+#A-<1|#8w2Mj6O9eO;Be8Hggdu@W^P1ke77K3V4&j~%8TvF2LxSlwTt_Q;J@xhpo zq%-kC?s@@3!CI_cymklj-=4(7(F7=pCV6zyc=Xm zLNes-QY<-U?FFo+y+Qea`ULHPForDIEL5^ZXehxznS28#sie9=Iax2aU3-M4?mZ)R kkC--7X9OyLp!Hr6->{*?ZMo1hN} z>Id|rqBAKZ)Z$*=J?EZt5AXBq?E}CbR&AJAu&|gx3Pl?lN*2l%mIP8VisVS3cv%84nJ|R=x4P}pkO0$6`Y|U+9jelYCdjyMy>>7(ViOlh}%{k$+-YbM>yhD42 z{zyQ;VV{T2z77K$oHvt2ViV~;xx}oni5wmB HKTCygXD3y! literal 0 HcmV?d00001 diff --git a/regression/jbmc-strings/max-length-generic-array/test.desc b/regression/jbmc-strings/max-length-generic-array/test.desc new file mode 100644 index 00000000000..3862a4978b3 --- /dev/null +++ b/regression/jbmc-strings/max-length-generic-array/test.desc @@ -0,0 +1,19 @@ +CORE +IntegerTests.class +-refine-strings --string-max-length 100 IntegerTests.class --function IntegerTests.testMySet --cover location +^EXIT=0$ +^SIGNAL=0$ +coverage.* line 12 function java::IntegerTests.testMySet.* bytecode-index 1 .* SATISFIED +coverage.* line 12 function java::IntegerTests.testMySet.* bytecode-index 3 .* SATISFIED +coverage.* line 13 function java::IntegerTests.testMySet.* bytecode-index 4 .* SATISFIED +coverage.* line 13 function java::IntegerTests.testMySet.* bytecode-index 6 .* SATISFIED +coverage.* line 13 function java::IntegerTests.testMySet.* bytecode-index 7 .* SATISFIED +coverage.* line 14 function java::IntegerTests.testMySet.* bytecode-index 12 .* SATISFIED +coverage.* line 14 function java::IntegerTests.testMySet.* bytecode-index 13 .* SATISFIED +coverage.* line 15 function java::IntegerTests.testMySet.* bytecode-index 16 .* SATISFIED +coverage.* line 15 function java::IntegerTests.testMySet.* bytecode-index 17 .* SATISFIED +coverage.* line 16 function java::IntegerTests.testMySet.* bytecode-index 21 .* SATISFIED +coverage.* line 15 function java::IntegerTests.testMySet.* bytecode-index 19 .* SATISFIED +coverage.* line 15 function java::IntegerTests.testMySet.* bytecode-index 20 .* SATISFIED +coverage.* line 16 function java::IntegerTests.testMySet.* bytecode-index 22 .* SATISFIED +coverage.* line 16 function java::IntegerTests.testMySet.* bytecode-index 23 .* SATISFIED diff --git a/regression/jbmc-strings/max-length-generic-array/test_gen.desc b/regression/jbmc-strings/max-length-generic-array/test_gen.desc new file mode 100644 index 00000000000..ec123c9a16a --- /dev/null +++ b/regression/jbmc-strings/max-length-generic-array/test_gen.desc @@ -0,0 +1,20 @@ +CORE +IntegerTests.class +-refine-strings --string-max-length 100 IntegerTests.class --function IntegerTests.testMyGenSet --cover location +^EXIT=0$ +^SIGNAL=0$ +coverage.* line 4 function java::IntegerTests.testMyGenSet.* bytecode-index 1 .* SATISFIED +coverage.* line 4 function java::IntegerTests.testMyGenSet.* bytecode-index 3 .* SATISFIED +coverage.* line 5 function java::IntegerTests.testMyGenSet.* bytecode-index 4 .* SATISFIED +coverage.* line 5 function java::IntegerTests.testMyGenSet.* bytecode-index 6 .* SATISFIED +coverage.* line 5 function java::IntegerTests.testMyGenSet.* bytecode-index 7 .* SATISFIED +coverage.* line 6 function java::IntegerTests.testMyGenSet.* bytecode-index 10 .* SATISFIED +coverage.* line 6 function java::IntegerTests.testMyGenSet.* bytecode-index 13 .* SATISFIED +coverage.* line 6 function java::IntegerTests.testMyGenSet.* bytecode-index 14 .* SATISFIED +coverage.* line 7 function java::IntegerTests.testMyGenSet.* bytecode-index 17 .* SATISFIED +coverage.* line 7 function java::IntegerTests.testMyGenSet.* bytecode-index 18 .* SATISFIED +coverage.* line 8 function java::IntegerTests.testMyGenSet.* bytecode-index 22 .* SATISFIED +coverage.* line 7 function java::IntegerTests.testMyGenSet.* bytecode-index 20 .* SATISFIED +coverage.* line 7 function java::IntegerTests.testMyGenSet.* bytecode-index 21 .* SATISFIED +coverage.* line 8 function java::IntegerTests.testMyGenSet.* bytecode-index 23 .* SATISFIED +coverage.* line 8 function java::IntegerTests.testMyGenSet.* bytecode-index 24 .* SATISFIED From 109b408cecaa8dc21e85a817de25896368120c5c Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Fri, 23 Feb 2018 09:51:53 +0000 Subject: [PATCH 25/93] Add tests showing the effect on string-max-length These tests show how the result of the solver can depend on the string-max-input-length and string-max-length parameters. --- regression/jbmc-strings/max-length/Test.class | Bin 0 -> 1064 bytes regression/jbmc-strings/max-length/Test.java | 37 ++++++++++++++++++ regression/jbmc-strings/max-length/test1.desc | 6 +++ regression/jbmc-strings/max-length/test2.desc | 6 +++ regression/jbmc-strings/max-length/test3.desc | 6 +++ regression/jbmc-strings/max-length/test4.desc | 11 ++++++ 6 files changed, 66 insertions(+) create mode 100644 regression/jbmc-strings/max-length/Test.class create mode 100644 regression/jbmc-strings/max-length/Test.java create mode 100644 regression/jbmc-strings/max-length/test1.desc create mode 100644 regression/jbmc-strings/max-length/test2.desc create mode 100644 regression/jbmc-strings/max-length/test3.desc create mode 100644 regression/jbmc-strings/max-length/test4.desc diff --git a/regression/jbmc-strings/max-length/Test.class b/regression/jbmc-strings/max-length/Test.class new file mode 100644 index 0000000000000000000000000000000000000000..0bc43cd0bdbcf889136c6b16a07dfa40f3004bb0 GIT binary patch literal 1064 zcmZva?N8HC6vm&sb?ep@_JWKz+2nm2$P`hd5*4Q=L{JmZMEqjuno%4b={jQKf5I2V zFMdW7Ae!JeP5hgT@wsJeF)U4QZ_hpbJ?A{9zyE$a0Wgo78oH2)B8IGnOBe|v{@}if zQ4JwvWMoXkI3_eEOv+_SMNUH=1r^f*J>y2bZn>UabLtQ6y0KBU$^v3tAiQ8Zws%(` zn9IKuP)fD3B@kb>9qVahd&6?qWHJfnre(feG2SgXI}LByaw^`Yz*KH|%h)xFRl}(i zS3TEuDtFFDB)DtUGvxO>ORLtwR zjvE4rHsIODmSuYXg-*Msk=3RrG;)crX3a4TrcQRSD1W{`fq|M^DVjTOZP#*(rRV;$ z1vfVhcagMo2ij7;#EG?wELAydrk1U`?ONql)0}|U-~kI<#|ZzCF8)~}(J$@dE(G?4 zB-a$*hWQjSS~!9@kcsHw8uo(%5os6qGW7)lynxBVPpH$spd5TbU=IU@Lj>el{^cr7YK581zesLE-TqWK|wVcre&3Z5BGBfYd4K9rK))|1bdeGP4F3Zv9L;n9 literal 0 HcmV?d00001 diff --git a/regression/jbmc-strings/max-length/Test.java b/regression/jbmc-strings/max-length/Test.java new file mode 100644 index 00000000000..e947169506d --- /dev/null +++ b/regression/jbmc-strings/max-length/Test.java @@ -0,0 +1,37 @@ +public class Test { + + static void checkMaxInputLength(String arg1, String arg2) { + // Filter + if (arg1 == null || arg2 == null) + return; + + // The validity of this depends on string-max-input-length + assert arg1.length() + arg2.length() < 1_000_000; + } + + static void checkMaxLength(String arg1, String arg2) { + // Filter + if (arg1 == null || arg2 == null) + return; + + if(arg1.length() + arg2.length() < 4_001) + return; + + // Act + String s = arg1.concat(arg2); + + // When string-max-length is smaller than 4_000 this will + // always be the case + assert org.cprover.CProverString.charAt(s, 4_000) == '?'; + } + + static void main(String argv[]) { + // Filter + if (argv.length < 2) + return; + + // Act + checkMaxInputLength(argv[0], argv[1]); + checkMaxLength(argv[0], argv[1]); + } +} diff --git a/regression/jbmc-strings/max-length/test1.desc b/regression/jbmc-strings/max-length/test1.desc new file mode 100644 index 00000000000..1cdaf80b01e --- /dev/null +++ b/regression/jbmc-strings/max-length/test1.desc @@ -0,0 +1,6 @@ +CORE +Test.class +--refine-strings --verbosity 10 --string-max-input-length 499999 --function Test.checkMaxInputLength +^EXIT=0$ +^SIGNAL=0$ +assertion.* line 9 function java::Test.checkMaxInputLength.* bytecode-index 16: SUCCESS diff --git a/regression/jbmc-strings/max-length/test2.desc b/regression/jbmc-strings/max-length/test2.desc new file mode 100644 index 00000000000..e705d18deda --- /dev/null +++ b/regression/jbmc-strings/max-length/test2.desc @@ -0,0 +1,6 @@ +CORE +Test.class +--refine-strings --verbosity 10 --string-max-input-length 500000 --function Test.checkMaxInputLength +^EXIT=10$ +^SIGNAL=0$ +assertion.* line 9 function java::Test.checkMaxInputLength.* bytecode-index 16: FAILURE diff --git a/regression/jbmc-strings/max-length/test3.desc b/regression/jbmc-strings/max-length/test3.desc new file mode 100644 index 00000000000..ab4c3b62db5 --- /dev/null +++ b/regression/jbmc-strings/max-length/test3.desc @@ -0,0 +1,6 @@ +CORE +Test.class +--refine-strings --verbosity 10 --string-max-length 4001 --function Test.checkMaxLength +^EXIT=10$ +^SIGNAL=0$ +assertion.* line 25 function java::Test.checkMaxLength.* bytecode-index 26: FAILURE diff --git a/regression/jbmc-strings/max-length/test4.desc b/regression/jbmc-strings/max-length/test4.desc new file mode 100644 index 00000000000..b1cdfc3d39c --- /dev/null +++ b/regression/jbmc-strings/max-length/test4.desc @@ -0,0 +1,11 @@ +CORE +Test.class +--refine-strings --verbosity 10 --string-max-length 4000 --function Test.checkMaxLength +^SIGNAL=0$ +-- +^EXIT=0$ +assertion.* line 25 function java::Test.checkMaxLength.* bytecode-index 26: SUCCESS +-- +The solver may give an ERROR because the value of string-max-length is too +small to give an answer about the assertion. +So we just check that the answer is not success. From 9593131c4acc041c3ebd86a297c351b85362615a Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 16 Apr 2018 08:02:12 +0100 Subject: [PATCH 26/93] Deprecate string-max-length option --- src/cbmc/cbmc_parse_options.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cbmc/cbmc_parse_options.cpp b/src/cbmc/cbmc_parse_options.cpp index 5962d65ecc9..e7189f965d1 100644 --- a/src/cbmc/cbmc_parse_options.cpp +++ b/src/cbmc/cbmc_parse_options.cpp @@ -999,8 +999,9 @@ void cbmc_parse_optionst::help() " --refine use refinement procedure (experimental)\n" " --refine-strings use string refinement (experimental)\n" " --string-printable add constraint that strings are printable (experimental)\n" // NOLINT(*) - " --string-max-length add constraint on the length of strings\n" // NOLINT(*) " --string-max-input-length add constraint on the length of input strings\n" // NOLINT(*) + " --string-max-length add constraint on the length of strings" + " (deprecated: use string-max-input-length instead)\n" // NOLINT(*) " --outfile filename output formula to given file\n" " --arrays-uf-never never turn arrays into uninterpreted functions\n" // NOLINT(*) " --arrays-uf-always always turn arrays into uninterpreted functions\n" // NOLINT(*) From b4328e976e43dbaea5433158420d85dd65469fe0 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Mon, 16 Apr 2018 08:27:57 +0100 Subject: [PATCH 27/93] Move MAX_CONCRETE_STRING_SIZE definition to magic --- src/solvers/refinement/string_refinement.cpp | 1 + src/solvers/refinement/string_refinement.h | 2 -- src/util/magic.h | 2 ++ 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index 52539307f0f..7a080dd361a 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -28,6 +28,7 @@ Author: Alberto Griggio, alberto.griggio@gmail.com #include #include #include +#include static bool is_valid_string_constraint( messaget::mstreamt &stream, diff --git a/src/solvers/refinement/string_refinement.h b/src/solvers/refinement/string_refinement.h index f33c1bcf0b0..ec7892838ed 100644 --- a/src/solvers/refinement/string_refinement.h +++ b/src/solvers/refinement/string_refinement.h @@ -31,8 +31,6 @@ Author: Alberto Griggio, alberto.griggio@gmail.com #define DEFAULT_MAX_NB_REFINEMENT std::numeric_limits::max() #define CHARACTER_FOR_UNKNOWN '?' -// Limit the size of strings in traces to 64M chars to avoid memout -#define MAX_CONCRETE_STRING_SIZE (1 << 26) class string_refinementt final: public bv_refinementt { diff --git a/src/util/magic.h b/src/util/magic.h index 48c72436e2d..3d1c2ed8d90 100644 --- a/src/util/magic.h +++ b/src/util/magic.h @@ -10,5 +10,7 @@ const std::size_t CNF_DUMP_BLOCK_SIZE = 4096; const std::size_t MAX_FLATTENED_ARRAY_SIZE=1000; const std::size_t STRING_REFINEMENT_MAX_CHAR_WIDTH = 16; +// Limit the size of strings in traces to 64M chars to avoid memout +const std::size_t MAX_CONCRETE_STRING_SIZE = 1 << 26; #endif From feb7ec091d63e82d9a2d33453ff26e435fcc172d Mon Sep 17 00:00:00 2001 From: Daniel Poetzl Date: Thu, 12 Apr 2018 15:00:17 +0100 Subject: [PATCH 28/93] Small shared two way pointer --- src/util/small_shared_two_way_ptr.h | 287 +++++++++++++++++++++++++ unit/Makefile | 1 + unit/util/small_shared_two_way_ptr.cpp | 103 +++++++++ 3 files changed, 391 insertions(+) create mode 100644 src/util/small_shared_two_way_ptr.h create mode 100644 unit/util/small_shared_two_way_ptr.cpp diff --git a/src/util/small_shared_two_way_ptr.h b/src/util/small_shared_two_way_ptr.h new file mode 100644 index 00000000000..7758411210f --- /dev/null +++ b/src/util/small_shared_two_way_ptr.h @@ -0,0 +1,287 @@ +/*******************************************************************\ + +Module: Small shared two-way pointer + +Author: Daniel Poetzl + +\*******************************************************************/ + +#ifndef CPROVER_UTIL_SMALL_SHARED_TWO_WAY_PTR_H +#define CPROVER_UTIL_SMALL_SHARED_TWO_WAY_PTR_H + +#include +#include +#include + +#include "invariant.h" + +template +class small_shared_two_way_pointeet; + +/// This class is similar to small_shared_ptrt and boost's intrusive_ptr. Like +/// those, it stores the use count with the pointed-to object instead of in a +/// separate control block. Additionally, it uses the MSB of the use count to +/// indicate the type of the managed object (which is either of type U or V). +/// +/// A possible use case is the implementation of data structures with sharing +/// that consist of two different types of objects (such as a tree with internal +/// nodes and leaf nodes). Storing the type with the use count avoids having to +/// keep a separate `type` member or using `typeid` or `dynamic_cast`. Moreover, +/// since the shared pointer is aware of the concrete type of the object being +/// stored, it can delete it without requiring a virtual destructor or custom +/// delete function (like std::shared_ptr). +template +class small_shared_two_way_ptrt final +{ +public: + typedef decltype(std::declval().use_count()) use_countt; + + typedef small_shared_two_way_pointeet pointeet; + + static_assert(std::is_base_of::value, ""); + static_assert(std::is_base_of::value, ""); + + small_shared_two_way_ptrt() = default; + + explicit small_shared_two_way_ptrt(U *u) : p(u) + { + PRECONDITION(u != nullptr); + PRECONDITION(u->use_count() == 0); + + p->set_derived_u(); + p->increment_use_count(); + } + + explicit small_shared_two_way_ptrt(V *v) : p(v) + { + PRECONDITION(v != nullptr); + PRECONDITION(v->use_count() == 0); + + p->set_derived_v(); + p->increment_use_count(); + } + + small_shared_two_way_ptrt(const small_shared_two_way_ptrt &rhs) : p(rhs.p) + { + PRECONDITION(is_same_type(rhs)); + + if(p) + { + p->increment_use_count(); + } + } + + small_shared_two_way_ptrt(small_shared_two_way_ptrt &&rhs) + { + PRECONDITION(is_same_type(rhs)); + + swap(rhs); + } + + small_shared_two_way_ptrt &operator=(const small_shared_two_way_ptrt &rhs) + { + PRECONDITION(is_same_type(rhs)); + + small_shared_two_way_ptrt copy(rhs); + swap(copy); + return *this; + } + + small_shared_two_way_ptrt &operator=(small_shared_two_way_ptrt &&rhs) + { + PRECONDITION(is_same_type(rhs)); + + swap(rhs); + return *this; + } + + ~small_shared_two_way_ptrt() + { + if(!p) + { + return; + } + + auto use_count = p->use_count(); + + if(use_count == 1) + { + if(p->is_derived_u()) + { + U *u = static_cast(p); + delete u; + } + else + { + V *v = static_cast(p); + delete v; + } + } + else + { + p->decrement_use_count(); + } + } + + void swap(small_shared_two_way_ptrt &rhs) + { + PRECONDITION(is_same_type(rhs)); + + std::swap(p, rhs.p); + } + + use_countt use_count() const + { + return p ? p->use_count() : 0; + } + + /// Checks if converting the held raw pointer to `U*` is valid + bool is_derived_u() const + { + return p == nullptr || p->is_derived_u(); + } + + /// Checks if converting the held raw pointer to `V*` is valid + bool is_derived_v() const + { + return p == nullptr || p->is_derived_v(); + } + + pointeet *get() const + { + return p; + } + + U *get_derived_u() const + { + PRECONDITION(is_derived_u()); + + return static_cast(p); + } + + V *get_derived_v() const + { + PRECONDITION(is_derived_v()); + + return static_cast(p); + } + + /// Checks if the raw pointers held by `*this` and `other` both can be + /// converted to either U* or V* + bool is_same_type(const small_shared_two_way_ptrt &other) const + { + if(p == nullptr || other.p == nullptr) + return true; + + return p->is_same_type(*other.p); + } + + explicit operator bool() const + { + return p != nullptr; + } + +private: + pointeet *p = nullptr; +}; + +template +small_shared_two_way_ptrt make_shared_derived_u(Ts &&... ts) +{ + return small_shared_two_way_ptrt(new U(std::forward(ts)...)); +} + +template +small_shared_two_way_ptrt make_shared_derived_v(Ts &&... ts) +{ + return small_shared_two_way_ptrt(new V(std::forward(ts)...)); +} + +template +bool operator==( + const small_shared_two_way_ptrt &lhs, + const small_shared_two_way_ptrt &rhs) +{ + return lhs.get() == rhs.get(); +} + +template +bool operator!=( + const small_shared_two_way_ptrt &lhs, + const small_shared_two_way_ptrt &rhs) +{ + return lhs.get() != rhs.get(); +} + +template +class small_shared_two_way_pointeet +{ +public: + static_assert(std::is_unsigned::value, ""); + + static const int bit_idx = std::numeric_limits::digits - 1; + static const Num mask = ~((Num)1 << bit_idx); + + small_shared_two_way_pointeet() = default; + + // The use count shall be unaffected + small_shared_two_way_pointeet(const small_shared_two_way_pointeet &rhs) + { + } + + // The use count shall be unaffected + small_shared_two_way_pointeet & + operator=(const small_shared_two_way_pointeet &rhs) + { + return *this; + } + + Num use_count() const + { + return use_count_ & mask; + } + + void increment_use_count() + { + PRECONDITION((use_count_ & mask) < mask); + + use_count_++; + } + + void decrement_use_count() + { + PRECONDITION((use_count_ & mask) > 0); + + use_count_--; + } + + void set_derived_u() + { + use_count_ &= mask; + } + + void set_derived_v() + { + use_count_ |= ~mask; + } + + bool is_derived_u() const + { + return !(use_count_ & ~mask); + } + + bool is_derived_v() const + { + return use_count_ & ~mask; + } + + bool is_same_type(const small_shared_two_way_pointeet &other) const + { + return !((use_count_ ^ other.use_count_) & ~mask); + } + +private: + Num use_count_ = 0; +}; + +#endif diff --git a/unit/Makefile b/unit/Makefile index eaf35100e23..05f188506aa 100644 --- a/unit/Makefile +++ b/unit/Makefile @@ -47,6 +47,7 @@ SRC += unit_tests.cpp \ util/optional.cpp \ util/parameter_indices.cpp \ util/simplify_expr.cpp \ + util/small_shared_two_way_ptr.cpp \ util/string_utils/split_string.cpp \ util/string_utils/strip_string.cpp \ util/symbol_table.cpp \ diff --git a/unit/util/small_shared_two_way_ptr.cpp b/unit/util/small_shared_two_way_ptr.cpp new file mode 100644 index 00000000000..7ca44c94e2c --- /dev/null +++ b/unit/util/small_shared_two_way_ptr.cpp @@ -0,0 +1,103 @@ +/// Author: Daniel Poetzl + +/// \file Tests for small shared two-way pointer + +#include +#include + +class d1t : public small_shared_two_way_pointeet +{ +public: + d1t() = default; + + explicit d1t(int i) : d1(i) + { + } + + int d1; +}; + +class d2t : public small_shared_two_way_pointeet +{ +public: + d2t() = default; + + explicit d2t(int i) : d2(i) + { + } + + int d2; +}; + +TEST_CASE("Small shared two-way pointer") +{ + typedef small_shared_two_way_ptrt spt; + + SECTION("Types") + { + spt sp1; + spt sp2(new d1t()); + spt sp3(new d2t()); + + REQUIRE(sp1.is_same_type(sp1)); + REQUIRE(sp2.is_same_type(sp2)); + REQUIRE(sp3.is_same_type(sp3)); + + REQUIRE(sp1.is_same_type(sp2)); + REQUIRE(sp1.is_same_type(sp3)); + + REQUIRE(!sp2.is_same_type(sp3)); + + REQUIRE(sp1.is_derived_u()); + REQUIRE(sp1.is_derived_v()); + + REQUIRE(sp2.is_derived_u()); + REQUIRE(!sp2.is_derived_v()); + + REQUIRE(sp3.is_derived_v()); + REQUIRE(!sp3.is_derived_u()); + } + + SECTION("Basic") + { + spt sp1; + REQUIRE(sp1.use_count() == 0); + + const d1t *p; + + p = sp1.get_derived_u(); + REQUIRE(p == nullptr); + + spt sp2(new d1t()); + REQUIRE(sp2.use_count() == 1); + + p = sp2.get_derived_u(); + REQUIRE(p != nullptr); + + spt sp3(sp2); + REQUIRE(sp3.is_derived_u()); + REQUIRE(sp2.get_derived_u() == sp3.get_derived_u()); + REQUIRE(sp2.use_count() == 2); + REQUIRE(sp3.use_count() == 2); + + sp1 = sp2; + REQUIRE(sp1.is_derived_u()); + REQUIRE(sp1.get_derived_u() == sp2.get_derived_u()); + REQUIRE(sp1.use_count() == 3); + REQUIRE(sp2.use_count() == 3); + REQUIRE(sp3.use_count() == 3); + } + + SECTION("Creation") + { + spt sp1 = make_shared_derived_u(); + spt sp2 = make_shared_derived_v(); + + REQUIRE(!sp1.is_same_type(sp2)); + + sp1 = make_shared_derived_u(0); + sp2 = make_shared_derived_v(0); + + REQUIRE(!sp1.is_same_type(sp2)); + } +} From 51323691e86815bfbb44806fe8a22cb8085796fd Mon Sep 17 00:00:00 2001 From: svorenova Date: Wed, 4 Apr 2018 10:16:25 +0100 Subject: [PATCH 29/93] Introduce nested exception printing --- src/util/Makefile | 1 + src/util/unwrap_nested_exception.cpp | 53 ++++++++++++++++++++++++++++ src/util/unwrap_nested_exception.h | 17 +++++++++ 3 files changed, 71 insertions(+) create mode 100644 src/util/unwrap_nested_exception.cpp create mode 100644 src/util/unwrap_nested_exception.h diff --git a/src/util/Makefile b/src/util/Makefile index cb9d221dd60..74fc5aec412 100644 --- a/src/util/Makefile +++ b/src/util/Makefile @@ -96,6 +96,7 @@ SRC = arith_tools.cpp \ unicode.cpp \ union_find.cpp \ union_find_replace.cpp \ + unwrap_nested_exception.cpp \ xml.cpp \ xml_expr.cpp \ xml_irep.cpp \ diff --git a/src/util/unwrap_nested_exception.cpp b/src/util/unwrap_nested_exception.cpp new file mode 100644 index 00000000000..a025376a0d0 --- /dev/null +++ b/src/util/unwrap_nested_exception.cpp @@ -0,0 +1,53 @@ +/*******************************************************************\ + +Module: util + +Author: Diffblue Ltd. + +\*******************************************************************/ + +#include "unwrap_nested_exception.h" +#include "invariant.h" +#include "string_utils.h" +#include "suffix.h" + +#include +#include + +/// Given a potentially nested exception, produce a string with all of nested +/// exceptions information. If a nested exception string contains new lines +/// then the newlines are indented to the correct level. +/// \param e: The outer exeception +/// \param level: How many exceptions have already been unrolled +/// \return A string with all nested exceptions printed and indented +std::string unwrap_exception(const std::exception &e, int level) +{ + const std::string msg = e.what(); + std::vector lines; + split_string(msg, '\n', lines, false, true); + std::ostringstream message_stream; + message_stream << std::string(level, ' ') << "exception: "; + join_strings( + message_stream, lines.begin(), lines.end(), "\n" + std::string(level, ' ')); + + try + { + std::rethrow_if_nested(e); + } + catch(const std::exception &e) + { + std::string nested_message = unwrap_exception(e, level + 1); + // Some exception messages already end in a new line (e.g. as they have + // dumped an irept. Most do not so add a new line on. + if(nested_message.back() != '\n') + { + message_stream << '\n'; + } + message_stream << nested_message; + } + catch(...) + { + UNREACHABLE; + } + return message_stream.str(); +} diff --git a/src/util/unwrap_nested_exception.h b/src/util/unwrap_nested_exception.h new file mode 100644 index 00000000000..4e2903c2c00 --- /dev/null +++ b/src/util/unwrap_nested_exception.h @@ -0,0 +1,17 @@ +/*******************************************************************\ + +Module: util + +Author: Diffblue Ltd. + +\*******************************************************************/ + +#ifndef CPROVER_UTIL_UNWRAP_NESTED_EXCEPTION_H +#define CPROVER_UTIL_UNWRAP_NESTED_EXCEPTION_H + +#include +#include + +std::string unwrap_exception(const std::exception &e, int level = 0); + +#endif // CPROVER_UTIL_UNWRAP_NESTED_EXCEPTION_H From 6b838b23ea800ba4e7893204ecaa4ffc93d5fd4e Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 9 Apr 2018 17:18:47 +0100 Subject: [PATCH 30/93] Convert flatten_byte_extract to use structured exceptions Store error in string to avoid dangling pointers --- .../flatten_byte_extract_exceptions.h | 144 ++++++++++++++++++ .../flattening/flatten_byte_operators.cpp | 23 ++- 2 files changed, 160 insertions(+), 7 deletions(-) create mode 100644 src/solvers/flattening/flatten_byte_extract_exceptions.h diff --git a/src/solvers/flattening/flatten_byte_extract_exceptions.h b/src/solvers/flattening/flatten_byte_extract_exceptions.h new file mode 100644 index 00000000000..f8c389bcbe4 --- /dev/null +++ b/src/solvers/flattening/flatten_byte_extract_exceptions.h @@ -0,0 +1,144 @@ +/*******************************************************************\ + +Module: Byte flattening + +Author: Diffblue Ltd. + +\*******************************************************************/ + +#ifndef CPROVER_SOLVERS_FLATTENING_FLATTEN_BYTE_EXTRACT_EXCEPTIONS_H +#define CPROVER_SOLVERS_FLATTENING_FLATTEN_BYTE_EXTRACT_EXCEPTIONS_H + +#include +#include +#include + +#include +#include + +class flatten_byte_extract_exceptiont : public std::runtime_error +{ +public: + explicit flatten_byte_extract_exceptiont(const std::string &exception_message) + : runtime_error(exception_message) + { + } +}; + +class non_const_array_sizet : public flatten_byte_extract_exceptiont +{ +public: + non_const_array_sizet(const array_typet &array_type, const exprt &max_bytes) + : flatten_byte_extract_exceptiont("cannot unpack array of non-const size"), + max_bytes(max_bytes), + array_type(array_type) + { + std::ostringstream error_message; + error_message << runtime_error::what() << "\n"; + error_message << "array_type: " << array_type.pretty(); + error_message << "\nmax_bytes: " << max_bytes.pretty(); + computed_error_message = error_message.str(); + } + + const char *what() const noexcept override + { + return computed_error_message.c_str(); + } + +private: + exprt max_bytes; + array_typet array_type; + + std::string computed_error_message; +}; + +class non_byte_alignedt : public flatten_byte_extract_exceptiont +{ +public: + non_byte_alignedt( + const struct_typet &struct_type, + const struct_union_typet::componentt &component, + const mp_integer &byte_width) + : flatten_byte_extract_exceptiont( + "cannot unpack struct with non-byte aligned components"), + struct_type(struct_type), + component(component), + byte_width(byte_width) + { + std::ostringstream error_message; + error_message << runtime_error::what() << "\n"; + error_message << "width: " << byte_width << "\n"; + error_message << "component:" << component.get_name() << "\n"; + error_message << "struct_type: " << struct_type.pretty(); + computed_error_message = error_message.str(); + } + + const char *what() const noexcept override + { + return computed_error_message.c_str(); + } + +private: + const struct_typet struct_type; + const struct_union_typet::componentt component; + const mp_integer byte_width; + + std::string computed_error_message; +}; + +class non_constant_widtht : public flatten_byte_extract_exceptiont +{ +public: +public: + non_constant_widtht(const exprt &src, const exprt &max_bytes) + : flatten_byte_extract_exceptiont( + "cannot unpack object of non-constant width"), + src(src), + max_bytes(max_bytes) + { + std::ostringstream error_message; + error_message << runtime_error::what() << "\n"; + error_message << "array_type: " << src.pretty(); + error_message << "\nmax_bytes: " << max_bytes.pretty(); + computed_error_message = error_message.str(); + } + + const char *what() const noexcept override + { + return computed_error_message.c_str(); + } + +private: + exprt src; + exprt max_bytes; + + std::string computed_error_message; +}; + +class non_const_byte_extraction_sizet : public flatten_byte_extract_exceptiont +{ +public: + explicit non_const_byte_extraction_sizet( + const byte_extract_exprt &unpack_expr) + : flatten_byte_extract_exceptiont( + "byte_extract flatting with non-constant size"), + unpack_expr(unpack_expr) + { + std::ostringstream error_message; + error_message << runtime_error::what() << "\n"; + error_message << "unpack_expr: " << unpack_expr.pretty(); + computed_error_message = error_message.str(); + } + + const char *what() const noexcept override + { + return computed_error_message.c_str(); + } + +private: + const byte_extract_exprt unpack_expr; + + std::string computed_error_message; +}; + +#endif // CPROVER_SOLVERS_FLATTENING_FLATTEN_BYTE_EXTRACT_EXCEPTIONS_H diff --git a/src/solvers/flattening/flatten_byte_operators.cpp b/src/solvers/flattening/flatten_byte_operators.cpp index c564b48df02..42054cc61dc 100644 --- a/src/solvers/flattening/flatten_byte_operators.cpp +++ b/src/solvers/flattening/flatten_byte_operators.cpp @@ -17,6 +17,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include "flatten_byte_extract_exceptions.h" #include "flatten_byte_operators.h" /// rewrite an object into its individual bytes @@ -25,6 +26,9 @@ Author: Daniel Kroening, kroening@kroening.com /// max_bytes if not nil, use as upper bound of the number of bytes to unpack /// ns namespace for type lookups /// \return array of bytes in the sequence found in memory +/// \throws flatten_byte_extract_exceptiont Raised is unable to unpack the +/// object because of either non constant size, byte misalignment or +/// non-constant component width. static exprt unpack_rec( const exprt &src, bool little_endian, @@ -63,7 +67,9 @@ static exprt unpack_rec( mp_integer num_elements; if(to_integer(max_bytes, num_elements) && to_integer(array_type.size(), num_elements)) - throw "cannot unpack array of non-const size:\n"+type.pretty(); + { + throw non_const_array_sizet(array_type, max_bytes); + } // all array members will have the same structure; do this just // once and then replace the dummy symbol by a suitable index @@ -97,8 +103,9 @@ static exprt unpack_rec( // the next member would be misaligned, abort if(element_width<=0 || element_width%8!=0) - throw "cannot unpack struct with non-byte aligned components:\n"+ - struct_type.pretty(); + { + throw non_byte_alignedt(struct_type, comp, element_width); + } member_exprt member(src, comp.get_name(), comp.type()); exprt sub=unpack_rec(member, little_endian, max_bytes, ns, true); @@ -115,8 +122,9 @@ static exprt unpack_rec( if(bits<0) { if(to_integer(max_bytes, bits)) - throw "cannot unpack object of non-constant width:\n"+ - src.pretty(); + { + throw non_constant_widtht(src, max_bytes); + } else bits*=8; } @@ -300,8 +308,9 @@ exprt flatten_byte_extract( { mp_integer op0_bits=pointer_offset_bits(unpacked.op().type(), ns); if(op0_bits<0) - throw "byte_extract flatting with non-constant size:\n"+ - unpacked.pretty(); + { + throw non_const_byte_extraction_sizet(unpacked); + } else size_bits=op0_bits; } From 0e3a6770e57f8af6db1a65d31a5f96a64ed7b21d Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 12 Apr 2018 14:20:51 +0100 Subject: [PATCH 31/93] Introduce throwing bv_conversion expection Remove suprisous namespace from bv_conversion_exceptions --- src/solvers/flattening/boolbv.cpp | 6 ++++ .../flattening/boolbv_byte_extract.cpp | 16 +++++++-- .../flattening/bv_conversion_exceptions.h | 34 +++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 src/solvers/flattening/bv_conversion_exceptions.h diff --git a/src/solvers/flattening/boolbv.cpp b/src/solvers/flattening/boolbv.cpp index a61e50a0f33..ba164134f17 100644 --- a/src/solvers/flattening/boolbv.cpp +++ b/src/solvers/flattening/boolbv.cpp @@ -152,6 +152,12 @@ bvt boolbvt::conversion_failed(const exprt &expr) return prop.new_variables(width); } +/// TODO +/// \param expr: TODO +/// \return TODO +/// \throws bitvector_conversion_exceptiont raised if converting byte_extraction +/// goes wrong. +/// TODO: extend for other types of conversion exception (diffblue/cbmc#2103). bvt boolbvt::convert_bitvector(const exprt &expr) { if(expr.type().id()==ID_bool) diff --git a/src/solvers/flattening/boolbv_byte_extract.cpp b/src/solvers/flattening/boolbv_byte_extract.cpp index 0cc2c46bd89..e550eeee362 100644 --- a/src/solvers/flattening/boolbv_byte_extract.cpp +++ b/src/solvers/flattening/boolbv_byte_extract.cpp @@ -11,10 +11,12 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include #include #include +#include +#include "bv_conversion_exceptions.h" +#include "flatten_byte_extract_exceptions.h" #include "flatten_byte_operators.h" bvt map_bv(const endianness_mapt &map, const bvt &src) @@ -42,8 +44,16 @@ bvt boolbvt::convert_byte_extract(const byte_extract_exprt &expr) // if we extract from an unbounded array, call the flattening code if(is_unbounded_array(expr.op().type())) { - exprt tmp=flatten_byte_extract(expr, ns); - return convert_bv(tmp); + try + { + exprt tmp = flatten_byte_extract(expr, ns); + return convert_bv(tmp); + } + catch(const flatten_byte_extract_exceptiont &byte_extract_flatten_exception) + { + std::throw_with_nested( + bitvector_conversion_exceptiont("Can't convert byte_extraction", expr)); + } } std::size_t width=boolbv_width(expr.type()); diff --git a/src/solvers/flattening/bv_conversion_exceptions.h b/src/solvers/flattening/bv_conversion_exceptions.h new file mode 100644 index 00000000000..2d3bbd2410b --- /dev/null +++ b/src/solvers/flattening/bv_conversion_exceptions.h @@ -0,0 +1,34 @@ +/*******************************************************************\ + +Module: Bit vector conversion + +Author: Diffblue Ltd. + +\*******************************************************************/ + +/// \file +/// Exceptions that can be raised in bv_conversion + +#ifndef CPROVER_SOLVERS_FLATTENING_BV_CONVERSION_EXCEPTIONS_H +#define CPROVER_SOLVERS_FLATTENING_BV_CONVERSION_EXCEPTIONS_H + +#include +#include + +#include + +class bitvector_conversion_exceptiont : public std::runtime_error +{ +public: + bitvector_conversion_exceptiont( + const std::string &exception_message, + const exprt &bv_expr) + : runtime_error(exception_message), bv_expr(bv_expr) + { + } + +private: + exprt bv_expr; +}; + +#endif // CPROVER_SOLVERS_FLATTENING_BV_CONVERSION_EXCEPTIONS_H From e63452183d77d840ebfe8b1f01a0142bc291e09c Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 12 Apr 2018 14:27:25 +0100 Subject: [PATCH 32/93] Introduce throwing a guard conversion exception Throw the unwrapped exception as a string --- .../equation_conversion_exceptions.h | 50 +++++++++++++++++++ src/goto-symex/symex_target_equation.cpp | 30 +++++++++-- 2 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 src/goto-symex/equation_conversion_exceptions.h diff --git a/src/goto-symex/equation_conversion_exceptions.h b/src/goto-symex/equation_conversion_exceptions.h new file mode 100644 index 00000000000..66dfcff195f --- /dev/null +++ b/src/goto-symex/equation_conversion_exceptions.h @@ -0,0 +1,50 @@ +/*******************************************************************\ + +Module: Symbolic Execution + +Author: Diffblue Ltd. + +\*******************************************************************/ + +/// \file +/// Exceptions that can be raised during the equation conversion phase + +#ifndef CPROVER_GOTO_SYMEX_EQUATION_CONVERSION_EXCEPTIONS_H +#define CPROVER_GOTO_SYMEX_EQUATION_CONVERSION_EXCEPTIONS_H + +#include +#include +#include "symex_target_equation.h" + +class guard_conversion_exceptiont : public std::runtime_error +{ +public: + guard_conversion_exceptiont( + const symex_target_equationt::SSA_stept &step, + const namespacet &ns) + : runtime_error("Error converting guard for step"), step(step) + { + std::ostringstream error_msg; + error_msg << runtime_error::what(); + error_msg << "\nStep:\n"; + step.output(ns, error_msg); + error_message = error_msg.str(); + } + + explicit guard_conversion_exceptiont( + const symex_target_equationt::SSA_stept &step) + : guard_conversion_exceptiont(step, namespacet{symbol_tablet{}}) + { + } + + const char *what() const noexcept override + { + return error_message.c_str(); + } + +private: + symex_target_equationt::SSA_stept step; + std::string error_message; +}; + +#endif // CPROVER_GOTO_SYMEX_EQUATION_CONVERSION_EXCEPTIONS_H diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 27be83608f1..62d6b4b9268 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -12,12 +12,15 @@ Author: Daniel Kroening, kroening@kroening.com #include "symex_target_equation.h" #include +#include #include -#include -#include +#include #include +#include +#include +#include "equation_conversion_exceptions.h" #include "goto_symex_state.h" /// read from a shared variable @@ -368,7 +371,17 @@ void symex_target_equationt::constraint( void symex_target_equationt::convert( prop_convt &prop_conv) { - convert_guards(prop_conv); + try + { + convert_guards(prop_conv); + } + catch(guard_conversion_exceptiont &guard_conversion_exception) + { + // unwrap the except and throw like normal + const std::string full_error = unwrap_exception(guard_conversion_exception); + throw full_error; + } + convert_assignments(prop_conv); convert_decls(prop_conv); convert_assumptions(prop_conv); @@ -417,7 +430,16 @@ void symex_target_equationt::convert_guards( if(step.ignore) step.guard_literal=const_literal(false); else - step.guard_literal=prop_conv.convert(step.guard); + { + try + { + step.guard_literal = prop_conv.convert(step.guard); + } + catch(const bitvector_conversion_exceptiont &conversion_exception) + { + std::throw_with_nested(guard_conversion_exceptiont(step)); + } + } } } From ab247870c78b4ae1ee34759e013c203dc715bac5 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 12 Apr 2018 17:02:06 +0100 Subject: [PATCH 33/93] Provide the original goto statement in the error This required the symex target_equation having the namespace to resolve names --- src/cbmc/bmc.h | 2 +- src/goto-instrument/accelerate/scratch_program.h | 2 +- src/goto-symex/equation_conversion_exceptions.h | 3 +++ src/goto-symex/symex_target_equation.cpp | 2 +- src/goto-symex/symex_target_equation.h | 8 +++++++- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/cbmc/bmc.h b/src/cbmc/bmc.h index 0f394199fe0..54f4affecdd 100644 --- a/src/cbmc/bmc.h +++ b/src/cbmc/bmc.h @@ -78,7 +78,7 @@ class bmct:public safety_checkert options(_options), outer_symbol_table(outer_symbol_table), ns(outer_symbol_table, symex_symbol_table), - equation(), + equation(ns), branch_worklist(_branch_worklist), symex(_message_handler, outer_symbol_table, equation, branch_worklist), prop_conv(_prop_conv), diff --git a/src/goto-instrument/accelerate/scratch_program.h b/src/goto-instrument/accelerate/scratch_program.h index 0bd76634bd0..afa58ba9fbb 100644 --- a/src/goto-instrument/accelerate/scratch_program.h +++ b/src/goto-instrument/accelerate/scratch_program.h @@ -40,7 +40,7 @@ class scratch_programt:public goto_programt symbol_table(_symbol_table), symex_symbol_table(), ns(symbol_table, symex_symbol_table), - equation(), + equation(ns), branch_worklist(), symex(mh, symbol_table, equation, branch_worklist), satcheck(util_make_unique()), diff --git a/src/goto-symex/equation_conversion_exceptions.h b/src/goto-symex/equation_conversion_exceptions.h index 66dfcff195f..2242d0bdc55 100644 --- a/src/goto-symex/equation_conversion_exceptions.h +++ b/src/goto-symex/equation_conversion_exceptions.h @@ -14,6 +14,7 @@ Author: Diffblue Ltd. #include #include +#include #include "symex_target_equation.h" class guard_conversion_exceptiont : public std::runtime_error @@ -26,6 +27,8 @@ class guard_conversion_exceptiont : public std::runtime_error { std::ostringstream error_msg; error_msg << runtime_error::what(); + error_msg << "\nSource GOTO statement: " + << from_expr(ns, "java", step.source.pc->code); error_msg << "\nStep:\n"; step.output(ns, error_msg); error_message = error_msg.str(); diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 62d6b4b9268..580d42f76e9 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -437,7 +437,7 @@ void symex_target_equationt::convert_guards( } catch(const bitvector_conversion_exceptiont &conversion_exception) { - std::throw_with_nested(guard_conversion_exceptiont(step)); + std::throw_with_nested(guard_conversion_exceptiont(step, ns)); } } } diff --git a/src/goto-symex/symex_target_equation.h b/src/goto-symex/symex_target_equation.h index 178cbeae7ab..c4c8cdf8910 100644 --- a/src/goto-symex/symex_target_equation.h +++ b/src/goto-symex/symex_target_equation.h @@ -32,7 +32,10 @@ class prop_convt; class symex_target_equationt:public symex_targett { public: - symex_target_equationt() = default; + explicit symex_target_equationt(const namespacet &ns) : ns(ns) + { + } + virtual ~symex_target_equationt() = default; // read event @@ -320,6 +323,9 @@ class symex_target_equationt:public symex_targett // for enforcing sharing in the expressions stored merge_irept merge_irep; void merge_ireps(SSA_stept &SSA_step); + +private: + const namespacet &ns; }; inline bool operator<( From 23760873ca5ba6c0d5cc47746f25d9258eb35c57 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 19 Apr 2018 15:07:28 +0100 Subject: [PATCH 34/93] Disable nested exception printing for Windows Due to bug in the VS2013 C++ compiler, using std::rethrow_if_nested or std::nested_exception is not supported. This disables trying to unwrap the exception and just prints a warning saying the nested exceptionc couldn't be printed. Don't use noexcept directly, pull both part of the nested exception into a separate file to handle discrepancies. --- .../equation_conversion_exceptions.h | 2 +- src/goto-symex/symex_target_equation.cpp | 3 +- .../flattening/boolbv_byte_extract.cpp | 3 +- .../flatten_byte_extract_exceptions.h | 8 +-- src/util/throw_with_nested.h | 60 +++++++++++++++++++ src/util/unwrap_nested_exception.cpp | 3 +- 6 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 src/util/throw_with_nested.h diff --git a/src/goto-symex/equation_conversion_exceptions.h b/src/goto-symex/equation_conversion_exceptions.h index 2242d0bdc55..41ca9f42a0b 100644 --- a/src/goto-symex/equation_conversion_exceptions.h +++ b/src/goto-symex/equation_conversion_exceptions.h @@ -40,7 +40,7 @@ class guard_conversion_exceptiont : public std::runtime_error { } - const char *what() const noexcept override + const char *what() const optional_noexcept override { return error_message.c_str(); } diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 580d42f76e9..7e97d6caf9a 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -12,6 +12,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "symex_target_equation.h" #include +#include #include #include @@ -437,7 +438,7 @@ void symex_target_equationt::convert_guards( } catch(const bitvector_conversion_exceptiont &conversion_exception) { - std::throw_with_nested(guard_conversion_exceptiont(step, ns)); + util_throw_with_nested(guard_conversion_exceptiont(step, ns)); } } } diff --git a/src/solvers/flattening/boolbv_byte_extract.cpp b/src/solvers/flattening/boolbv_byte_extract.cpp index e550eeee362..f3841a6f0f3 100644 --- a/src/solvers/flattening/boolbv_byte_extract.cpp +++ b/src/solvers/flattening/boolbv_byte_extract.cpp @@ -14,6 +14,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include +#include #include "bv_conversion_exceptions.h" #include "flatten_byte_extract_exceptions.h" @@ -51,7 +52,7 @@ bvt boolbvt::convert_byte_extract(const byte_extract_exprt &expr) } catch(const flatten_byte_extract_exceptiont &byte_extract_flatten_exception) { - std::throw_with_nested( + util_throw_with_nested( bitvector_conversion_exceptiont("Can't convert byte_extraction", expr)); } } diff --git a/src/solvers/flattening/flatten_byte_extract_exceptions.h b/src/solvers/flattening/flatten_byte_extract_exceptions.h index f8c389bcbe4..a5ae22791b3 100644 --- a/src/solvers/flattening/flatten_byte_extract_exceptions.h +++ b/src/solvers/flattening/flatten_byte_extract_exceptions.h @@ -40,7 +40,7 @@ class non_const_array_sizet : public flatten_byte_extract_exceptiont computed_error_message = error_message.str(); } - const char *what() const noexcept override + const char *what() const optional_noexcept override { return computed_error_message.c_str(); } @@ -73,7 +73,7 @@ class non_byte_alignedt : public flatten_byte_extract_exceptiont computed_error_message = error_message.str(); } - const char *what() const noexcept override + const char *what() const optional_noexcept override { return computed_error_message.c_str(); } @@ -103,7 +103,7 @@ class non_constant_widtht : public flatten_byte_extract_exceptiont computed_error_message = error_message.str(); } - const char *what() const noexcept override + const char *what() const optional_noexcept override { return computed_error_message.c_str(); } @@ -130,7 +130,7 @@ class non_const_byte_extraction_sizet : public flatten_byte_extract_exceptiont computed_error_message = error_message.str(); } - const char *what() const noexcept override + const char *what() const optional_noexcept override { return computed_error_message.c_str(); } diff --git a/src/util/throw_with_nested.h b/src/util/throw_with_nested.h new file mode 100644 index 00000000000..444a7a60e6b --- /dev/null +++ b/src/util/throw_with_nested.h @@ -0,0 +1,60 @@ +/*******************************************************************\ + +Module: util + +Author: Diffblue Ltd. + +\*******************************************************************/ + +#ifndef CPROVER_UTIL_THROW_WITH_NESTED_H +#define CPROVER_UTIL_THROW_WITH_NESTED_H + +#include + +#ifdef _MSC_VER +#include +// TODO(tkiley): Nested exception logging not supported on windows due to a bug +// TODO(tkiley): in MSVC++ Compiler (diffblue/cbmc#2104): +// TODO(tkiley): https://blogs.msdn.microsoft.com/vcblog/2016/01/22/vs-2015-update-2s-stl-is-c17-so-far-feature-complete + +#define DISABLE_NESTED_EXCEPTIONS + +class non_nested_exception_support : public std::runtime_error +{ +public: + non_nested_exception_support() + : std::runtime_error("Nested exception printing not supported on Windows") + { + } +}; + +#endif + +template +#ifdef __GNUC__ +__attribute__((noreturn)) +#endif +void util_throw_with_nested(T &&t) +{ +#ifndef DISABLE_NESTED_EXCEPTIONS + std::throw_with_nested(t); +#else + throw t; +#endif +} + +template +void util_rethrow_if_nested(const E &e) +{ +#ifndef DISABLE_NESTED_EXCEPTIONS + std::rethrow_if_nested(e); +#else + // Check we've not already thrown the non_nested_support_exception + if(!dynamic_cast(&e)) + { + throw non_nested_exception_support(); + } +#endif +} + +#endif // CPROVER_UTIL_THROW_WITH_NESTED_H diff --git a/src/util/unwrap_nested_exception.cpp b/src/util/unwrap_nested_exception.cpp index a025376a0d0..0689391466b 100644 --- a/src/util/unwrap_nested_exception.cpp +++ b/src/util/unwrap_nested_exception.cpp @@ -10,6 +10,7 @@ Author: Diffblue Ltd. #include "invariant.h" #include "string_utils.h" #include "suffix.h" +#include "throw_with_nested.h" #include #include @@ -32,7 +33,7 @@ std::string unwrap_exception(const std::exception &e, int level) try { - std::rethrow_if_nested(e); + util_rethrow_if_nested(e); } catch(const std::exception &e) { From 639a8f69234a8d250c55a8d44ea0ae41a586c904 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 19 Apr 2018 17:37:50 +0100 Subject: [PATCH 35/93] Test demonstrating logging with clause for dealing with Windows --- .../TestClass.class | Bin 0 -> 399 bytes .../TestClass.java | 7 +++++++ .../dynamic-multi-dimensional-array/test.desc | 10 ++++++++++ 3 files changed, 17 insertions(+) create mode 100644 regression/cbmc-java/dynamic-multi-dimensional-array/TestClass.class create mode 100644 regression/cbmc-java/dynamic-multi-dimensional-array/TestClass.java create mode 100644 regression/cbmc-java/dynamic-multi-dimensional-array/test.desc diff --git a/regression/cbmc-java/dynamic-multi-dimensional-array/TestClass.class b/regression/cbmc-java/dynamic-multi-dimensional-array/TestClass.class new file mode 100644 index 0000000000000000000000000000000000000000..66e0d0732425724aad3f598846515a0603e8f0c3 GIT binary patch literal 399 zcmYL_O-sW-5Qg7L(!`{-AMsl}=&dRk6mNbUEEEbs5lb&UZDQ1v*g}#D{wz;|2X9{d zQR2I;)LnLG=b4>%cJ}+{;}gIswmej@?!dRMJix(*gH3^bo{rPa{(@nI=EdR8iRqiS|3W_N lf|ndxmoI2iT8r+^6VV{iU+bX-pRz86SIG1$R~a#|_6z5sIxGMH literal 0 HcmV?d00001 diff --git a/regression/cbmc-java/dynamic-multi-dimensional-array/TestClass.java b/regression/cbmc-java/dynamic-multi-dimensional-array/TestClass.java new file mode 100644 index 00000000000..16d680bd804 --- /dev/null +++ b/regression/cbmc-java/dynamic-multi-dimensional-array/TestClass.java @@ -0,0 +1,7 @@ +public class TestClass { + public static void f(int y) { + float[][] a1 = new float[y][3]; + int j = 0; + a1[j][0] = 34.5f; + } +} diff --git a/regression/cbmc-java/dynamic-multi-dimensional-array/test.desc b/regression/cbmc-java/dynamic-multi-dimensional-array/test.desc new file mode 100644 index 00000000000..c9600f50852 --- /dev/null +++ b/regression/cbmc-java/dynamic-multi-dimensional-array/test.desc @@ -0,0 +1,10 @@ +CORE +TestClass.class +--function TestClass.f --cover location --unwind 2 +Source GOTO statement: .* +(^ exception: Can't convert byte_extraction|Nested exception printing not supported on Windows) +^EXIT=6$ +-- +-- +The exception thrown in this test is the symptom of a bug; the purpose of this +test is the validate the output of that exception From c3e24e08471655545f5213e7c5734df8f23a1d6f Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 23 Apr 2018 11:12:46 +0100 Subject: [PATCH 36/93] Add documentation to convert_bitvector --- src/solvers/flattening/boolbv.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/solvers/flattening/boolbv.cpp b/src/solvers/flattening/boolbv.cpp index ba164134f17..40ddc83e3d6 100644 --- a/src/solvers/flattening/boolbv.cpp +++ b/src/solvers/flattening/boolbv.cpp @@ -152,9 +152,11 @@ bvt boolbvt::conversion_failed(const exprt &expr) return prop.new_variables(width); } -/// TODO -/// \param expr: TODO -/// \return TODO +/// Converts an expression into its gate-level representation and returns a +/// vector of literals corresponding to the outputs of the Boolean circuit. +/// \param expr: Expression to convert +/// \return A vector of literals corresponding to the outputs of the Boolean +/// circuit /// \throws bitvector_conversion_exceptiont raised if converting byte_extraction /// goes wrong. /// TODO: extend for other types of conversion exception (diffblue/cbmc#2103). From 1810a7cba07c0cfe358125452d9d213f06f99928 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 23 Apr 2018 13:45:27 +0100 Subject: [PATCH 37/93] Introduce exceptions for all conversion steps. --- .../equation_conversion_exceptions.h | 15 ++-- src/goto-symex/symex_target_equation.cpp | 71 +++++++++++++++---- 2 files changed, 66 insertions(+), 20 deletions(-) diff --git a/src/goto-symex/equation_conversion_exceptions.h b/src/goto-symex/equation_conversion_exceptions.h index 41ca9f42a0b..099be66e239 100644 --- a/src/goto-symex/equation_conversion_exceptions.h +++ b/src/goto-symex/equation_conversion_exceptions.h @@ -13,17 +13,21 @@ Author: Diffblue Ltd. #define CPROVER_GOTO_SYMEX_EQUATION_CONVERSION_EXCEPTIONS_H #include + #include + #include + #include "symex_target_equation.h" -class guard_conversion_exceptiont : public std::runtime_error +class equation_conversion_exceptiont : public std::runtime_error { public: - guard_conversion_exceptiont( + equation_conversion_exceptiont( + const std::string &message, const symex_target_equationt::SSA_stept &step, const namespacet &ns) - : runtime_error("Error converting guard for step"), step(step) + : runtime_error(message), step(step) { std::ostringstream error_msg; error_msg << runtime_error::what(); @@ -34,9 +38,10 @@ class guard_conversion_exceptiont : public std::runtime_error error_message = error_msg.str(); } - explicit guard_conversion_exceptiont( + explicit equation_conversion_exceptiont( + const std::string &message, const symex_target_equationt::SSA_stept &step) - : guard_conversion_exceptiont(step, namespacet{symbol_tablet{}}) + : equation_conversion_exceptiont(message, step, namespacet{symbol_tablet{}}) { } diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 7e97d6caf9a..be6fd3a42c2 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -375,21 +375,20 @@ void symex_target_equationt::convert( try { convert_guards(prop_conv); + convert_assignments(prop_conv); + convert_decls(prop_conv); + convert_assumptions(prop_conv); + convert_assertions(prop_conv); + convert_goto_instructions(prop_conv); + convert_io(prop_conv); + convert_constraints(prop_conv); } - catch(guard_conversion_exceptiont &guard_conversion_exception) + catch(const equation_conversion_exceptiont &conversion_exception) { // unwrap the except and throw like normal - const std::string full_error = unwrap_exception(guard_conversion_exception); + const std::string full_error = unwrap_exception(conversion_exception); throw full_error; } - - convert_assignments(prop_conv); - convert_decls(prop_conv); - convert_assumptions(prop_conv); - convert_assertions(prop_conv); - convert_goto_instructions(prop_conv); - convert_io(prop_conv); - convert_constraints(prop_conv); } /// converts assignments @@ -416,7 +415,16 @@ void symex_target_equationt::convert_decls( { // The result is not used, these have no impact on // the satisfiability of the formula. - prop_conv.convert(step.cond_expr); + try + { + prop_conv.convert(step.cond_expr); + } + catch(const bitvector_conversion_exceptiont &conversion_exception) + { + util_throw_with_nested( + equation_conversion_exceptiont( + "Error converting decls for step", step, ns)); + } } } } @@ -438,7 +446,9 @@ void symex_target_equationt::convert_guards( } catch(const bitvector_conversion_exceptiont &conversion_exception) { - util_throw_with_nested(guard_conversion_exceptiont(step, ns)); + util_throw_with_nested( + equation_conversion_exceptiont( + "Error converting guard for step", step, ns)); } } } @@ -456,7 +466,18 @@ void symex_target_equationt::convert_assumptions( if(step.ignore) step.cond_literal=const_literal(true); else - step.cond_literal=prop_conv.convert(step.cond_expr); + { + try + { + step.cond_literal = prop_conv.convert(step.cond_expr); + } + catch(const bitvector_conversion_exceptiont &conversion_exception) + { + util_throw_with_nested( + equation_conversion_exceptiont( + "Error converting assumptions for step", step, ns)); + } + } } } } @@ -473,7 +494,18 @@ void symex_target_equationt::convert_goto_instructions( if(step.ignore) step.cond_literal=const_literal(true); else - step.cond_literal=prop_conv.convert(step.cond_expr); + { + try + { + step.cond_literal = prop_conv.convert(step.cond_expr); + } + catch(const bitvector_conversion_exceptiont &conversion_exception) + { + util_throw_with_nested( + equation_conversion_exceptiont( + "Error converting goto instructions for step", step, ns)); + } + } } } } @@ -542,7 +574,16 @@ void symex_target_equationt::convert_assertions( step.cond_expr); // do the conversion - step.cond_literal=prop_conv.convert(implication); + try + { + step.cond_literal = prop_conv.convert(implication); + } + catch(const bitvector_conversion_exceptiont &conversion_exception) + { + util_throw_with_nested( + equation_conversion_exceptiont( + "Error converting assertions for step", step, ns)); + } // store disjunct disjuncts.push_back(literal_exprt(!step.cond_literal)); From 37e712dde6d0653be2bbee91e16470dbecc6b148 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 23 Apr 2018 15:02:51 +0100 Subject: [PATCH 38/93] Use format rather than from_expr for output --- src/cbmc/bmc.h | 2 +- .../accelerate/scratch_program.h | 2 +- .../equation_conversion_exceptions.h | 19 +-- src/goto-symex/symex_target_equation.cpp | 111 +++++++++++++++++- src/goto-symex/symex_target_equation.h | 11 +- 5 files changed, 116 insertions(+), 29 deletions(-) diff --git a/src/cbmc/bmc.h b/src/cbmc/bmc.h index 54f4affecdd..0f394199fe0 100644 --- a/src/cbmc/bmc.h +++ b/src/cbmc/bmc.h @@ -78,7 +78,7 @@ class bmct:public safety_checkert options(_options), outer_symbol_table(outer_symbol_table), ns(outer_symbol_table, symex_symbol_table), - equation(ns), + equation(), branch_worklist(_branch_worklist), symex(_message_handler, outer_symbol_table, equation, branch_worklist), prop_conv(_prop_conv), diff --git a/src/goto-instrument/accelerate/scratch_program.h b/src/goto-instrument/accelerate/scratch_program.h index afa58ba9fbb..0bd76634bd0 100644 --- a/src/goto-instrument/accelerate/scratch_program.h +++ b/src/goto-instrument/accelerate/scratch_program.h @@ -40,7 +40,7 @@ class scratch_programt:public goto_programt symbol_table(_symbol_table), symex_symbol_table(), ns(symbol_table, symex_symbol_table), - equation(ns), + equation(), branch_worklist(), symex(mh, symbol_table, equation, branch_worklist), satcheck(util_make_unique()), diff --git a/src/goto-symex/equation_conversion_exceptions.h b/src/goto-symex/equation_conversion_exceptions.h index 099be66e239..f2055c1c9ec 100644 --- a/src/goto-symex/equation_conversion_exceptions.h +++ b/src/goto-symex/equation_conversion_exceptions.h @@ -14,9 +14,7 @@ Author: Diffblue Ltd. #include -#include - -#include +#include #include "symex_target_equation.h" @@ -25,26 +23,17 @@ class equation_conversion_exceptiont : public std::runtime_error public: equation_conversion_exceptiont( const std::string &message, - const symex_target_equationt::SSA_stept &step, - const namespacet &ns) + const symex_target_equationt::SSA_stept &step) : runtime_error(message), step(step) { std::ostringstream error_msg; error_msg << runtime_error::what(); - error_msg << "\nSource GOTO statement: " - << from_expr(ns, "java", step.source.pc->code); + error_msg << "\nSource GOTO statement: " << format(step.source.pc->code); error_msg << "\nStep:\n"; - step.output(ns, error_msg); + step.output(error_msg); error_message = error_msg.str(); } - explicit equation_conversion_exceptiont( - const std::string &message, - const symex_target_equationt::SSA_stept &step) - : equation_conversion_exceptiont(message, step, namespacet{symbol_tablet{}}) - { - } - const char *what() const optional_noexcept override { return error_message.c_str(); diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index be6fd3a42c2..4f3fca4e81e 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -11,11 +11,14 @@ Author: Daniel Kroening, kroening@kroening.com #include "symex_target_equation.h" +#include #include #include #include +// Can be removed once deprecated SSA_stept::output is removed #include + #include #include #include @@ -423,7 +426,7 @@ void symex_target_equationt::convert_decls( { util_throw_with_nested( equation_conversion_exceptiont( - "Error converting decls for step", step, ns)); + "Error converting decls for step", step)); } } } @@ -448,7 +451,7 @@ void symex_target_equationt::convert_guards( { util_throw_with_nested( equation_conversion_exceptiont( - "Error converting guard for step", step, ns)); + "Error converting guard for step", step)); } } } @@ -475,7 +478,7 @@ void symex_target_equationt::convert_assumptions( { util_throw_with_nested( equation_conversion_exceptiont( - "Error converting assumptions for step", step, ns)); + "Error converting assumptions for step", step)); } } } @@ -503,7 +506,7 @@ void symex_target_equationt::convert_goto_instructions( { util_throw_with_nested( equation_conversion_exceptiont( - "Error converting goto instructions for step", step, ns)); + "Error converting goto instructions for step", step)); } } } @@ -582,7 +585,7 @@ void symex_target_equationt::convert_assertions( { util_throw_with_nested( equation_conversion_exceptiont( - "Error converting assertions for step", step, ns)); + "Error converting assertions for step", step)); } // store disjunct @@ -767,3 +770,101 @@ void symex_target_equationt::SSA_stept::output( out << "Guard: " << from_expr(ns, source.pc->function, guard) << '\n'; } + +void symex_target_equationt::SSA_stept::output(std::ostream &out) const +{ + if(source.is_set) + { + out << "Thread " << source.thread_nr; + + if(source.pc->source_location.is_not_nil()) + out << " " << source.pc->source_location << '\n'; + else + out << '\n'; + } + + switch(type) + { + case goto_trace_stept::typet::ASSERT: + out << "ASSERT " << format(cond_expr) << '\n'; break; + case goto_trace_stept::typet::ASSUME: + out << "ASSUME " << format(cond_expr) << '\n'; break; + case goto_trace_stept::typet::LOCATION: + out << "LOCATION" << '\n'; break; + case goto_trace_stept::typet::INPUT: + out << "INPUT" << '\n'; break; + case goto_trace_stept::typet::OUTPUT: + out << "OUTPUT" << '\n'; break; + + case goto_trace_stept::typet::DECL: + out << "DECL" << '\n'; + out << format(ssa_lhs) << '\n'; + break; + + case goto_trace_stept::typet::ASSIGNMENT: + out << "ASSIGNMENT ("; + switch(assignment_type) + { + case assignment_typet::HIDDEN: + out << "HIDDEN"; + break; + case assignment_typet::STATE: + out << "STATE"; + break; + case assignment_typet::VISIBLE_ACTUAL_PARAMETER: + out << "VISIBLE_ACTUAL_PARAMETER"; + break; + case assignment_typet::HIDDEN_ACTUAL_PARAMETER: + out << "HIDDEN_ACTUAL_PARAMETER"; + break; + case assignment_typet::PHI: + out << "PHI"; + break; + case assignment_typet::GUARD: + out << "GUARD"; + break; + default: + { + } + } + + out << ")\n"; + break; + + case goto_trace_stept::typet::DEAD: + out << "DEAD\n"; break; + case goto_trace_stept::typet::FUNCTION_CALL: + out << "FUNCTION_CALL\n"; break; + case goto_trace_stept::typet::FUNCTION_RETURN: + out << "FUNCTION_RETURN\n"; break; + case goto_trace_stept::typet::CONSTRAINT: + out << "CONSTRAINT\n"; break; + case goto_trace_stept::typet::SHARED_READ: + out << "SHARED READ\n"; break; + case goto_trace_stept::typet::SHARED_WRITE: + out << "SHARED WRITE\n"; break; + case goto_trace_stept::typet::ATOMIC_BEGIN: + out << "ATOMIC_BEGIN\n"; break; + case goto_trace_stept::typet::ATOMIC_END: + out << "AUTOMIC_END\n"; break; + case goto_trace_stept::typet::SPAWN: + out << "SPAWN\n"; break; + case goto_trace_stept::typet::MEMORY_BARRIER: + out << "MEMORY_BARRIER\n"; break; + case goto_trace_stept::typet::GOTO: + out << "IF " << format(cond_expr) << " GOTO\n"; break; + + default: UNREACHABLE; + } + + if(is_assert() || is_assume() || is_assignment() || is_constraint()) + out << format(cond_expr) << '\n'; + + if(is_assert() || is_constraint()) + out << comment << '\n'; + + if(is_shared_read() || is_shared_write()) + out << format(ssa_lhs) << '\n'; + + out << "Guard: " << format(guard) << '\n'; +} diff --git a/src/goto-symex/symex_target_equation.h b/src/goto-symex/symex_target_equation.h index c4c8cdf8910..079158f0374 100644 --- a/src/goto-symex/symex_target_equation.h +++ b/src/goto-symex/symex_target_equation.h @@ -32,10 +32,7 @@ class prop_convt; class symex_target_equationt:public symex_targett { public: - explicit symex_target_equationt(const namespacet &ns) : ns(ns) - { - } - + symex_target_equationt() = default; virtual ~symex_target_equationt() = default; // read event @@ -260,9 +257,12 @@ class symex_target_equationt:public symex_targett { } + DEPRECATED("Use output without ns param") void output( const namespacet &ns, std::ostream &out) const; + + void output(std::ostream &out) const; }; std::size_t count_assertions() const @@ -323,9 +323,6 @@ class symex_target_equationt:public symex_targett // for enforcing sharing in the expressions stored merge_irept merge_irep; void merge_ireps(SSA_stept &SSA_step); - -private: - const namespacet &ns; }; inline bool operator<( From f64898f653706e4569542116aceec98b03e9a1f9 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 23 Apr 2018 17:11:55 +0100 Subject: [PATCH 39/93] Remove redundant default constructor --- src/goto-symex/symex_target_equation.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/goto-symex/symex_target_equation.h b/src/goto-symex/symex_target_equation.h index 079158f0374..bada3f9d871 100644 --- a/src/goto-symex/symex_target_equation.h +++ b/src/goto-symex/symex_target_equation.h @@ -32,7 +32,6 @@ class prop_convt; class symex_target_equationt:public symex_targett { public: - symex_target_equationt() = default; virtual ~symex_target_equationt() = default; // read event From 6cb3a3b9c908046bd3ccc1f2fb617b4d31b221d9 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 23 Apr 2018 17:22:22 +0100 Subject: [PATCH 40/93] Reformatting touched output function --- src/goto-symex/symex_target_equation.cpp | 51 ++++++++++++++++-------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/goto-symex/symex_target_equation.cpp b/src/goto-symex/symex_target_equation.cpp index 4f3fca4e81e..0d3709dde8e 100644 --- a/src/goto-symex/symex_target_equation.cpp +++ b/src/goto-symex/symex_target_equation.cpp @@ -786,15 +786,20 @@ void symex_target_equationt::SSA_stept::output(std::ostream &out) const switch(type) { case goto_trace_stept::typet::ASSERT: - out << "ASSERT " << format(cond_expr) << '\n'; break; + out << "ASSERT " << format(cond_expr) << '\n'; + break; case goto_trace_stept::typet::ASSUME: - out << "ASSUME " << format(cond_expr) << '\n'; break; + out << "ASSUME " << format(cond_expr) << '\n'; + break; case goto_trace_stept::typet::LOCATION: - out << "LOCATION" << '\n'; break; + out << "LOCATION" << '\n'; + break; case goto_trace_stept::typet::INPUT: - out << "INPUT" << '\n'; break; + out << "INPUT" << '\n'; + break; case goto_trace_stept::typet::OUTPUT: - out << "OUTPUT" << '\n'; break; + out << "OUTPUT" << '\n'; + break; case goto_trace_stept::typet::DECL: out << "DECL" << '\n'; @@ -832,29 +837,41 @@ void symex_target_equationt::SSA_stept::output(std::ostream &out) const break; case goto_trace_stept::typet::DEAD: - out << "DEAD\n"; break; + out << "DEAD\n"; + break; case goto_trace_stept::typet::FUNCTION_CALL: - out << "FUNCTION_CALL\n"; break; + out << "FUNCTION_CALL\n"; + break; case goto_trace_stept::typet::FUNCTION_RETURN: - out << "FUNCTION_RETURN\n"; break; + out << "FUNCTION_RETURN\n"; + break; case goto_trace_stept::typet::CONSTRAINT: - out << "CONSTRAINT\n"; break; + out << "CONSTRAINT\n"; + break; case goto_trace_stept::typet::SHARED_READ: - out << "SHARED READ\n"; break; + out << "SHARED READ\n"; + break; case goto_trace_stept::typet::SHARED_WRITE: - out << "SHARED WRITE\n"; break; + out << "SHARED WRITE\n"; + break; case goto_trace_stept::typet::ATOMIC_BEGIN: - out << "ATOMIC_BEGIN\n"; break; + out << "ATOMIC_BEGIN\n"; + break; case goto_trace_stept::typet::ATOMIC_END: - out << "AUTOMIC_END\n"; break; + out << "AUTOMIC_END\n"; + break; case goto_trace_stept::typet::SPAWN: - out << "SPAWN\n"; break; + out << "SPAWN\n"; + break; case goto_trace_stept::typet::MEMORY_BARRIER: - out << "MEMORY_BARRIER\n"; break; + out << "MEMORY_BARRIER\n"; + break; case goto_trace_stept::typet::GOTO: - out << "IF " << format(cond_expr) << " GOTO\n"; break; + out << "IF " << format(cond_expr) << " GOTO\n"; + break; - default: UNREACHABLE; + default: + UNREACHABLE; } if(is_assert() || is_assume() || is_assignment() || is_constraint()) From 5c5562bd28724c07e92ecbda299bbcd40ad7ce09 Mon Sep 17 00:00:00 2001 From: thk123 Date: Mon, 23 Apr 2018 15:27:55 +0100 Subject: [PATCH 41/93] Sort includes using clang-format In current version of clang-format, this leaves groupings alone and just sorts within the group. For example, given a list of includes like: ``` include "boolbv.h" include include include include include include ``` These will be sorted to: ``` include "boolbv.h" include include include include include include ``` Note the "groups" are left untouched, the ordering occurs within the groups --- .clang-format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-format b/.clang-format index 6d8c8f0b034..08fa2d1925c 100644 --- a/.clang-format +++ b/.clang-format @@ -84,7 +84,7 @@ NamespaceIndentation: None PenaltyBreakString: 10000 PointerAlignment: Right ReflowComments: 'false' -SortIncludes: 'false' +SortIncludes: 'true' SpaceAfterCStyleCast: 'false' SpaceBeforeAssignmentOperators: 'true' SpaceBeforeParens: Never From de34bee1513a37962121dc6f4e99528696f2d2ab Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Mon, 23 Apr 2018 16:23:48 +0000 Subject: [PATCH 42/93] Make virtual function resolution independent of string table entry ordering The program generated by virtual-function removal depended on where 'B', 'C', 'D', 'E' appear in the string table as there are multiple semantically equivalent resolutions of virtual functions. --- regression/cbmc-java/virtual7/test.desc | 4 ++-- src/goto-programs/remove_virtual_functions.cpp | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/regression/cbmc-java/virtual7/test.desc b/regression/cbmc-java/virtual7/test.desc index 7d23df44236..900469e7dcf 100644 --- a/regression/cbmc-java/virtual7/test.desc +++ b/regression/cbmc-java/virtual7/test.desc @@ -3,6 +3,6 @@ test.class --show-goto-functions --function test.main ^EXIT=0$ ^SIGNAL=0$ -IF.*"java::C".*THEN GOTO -IF.*"java::D".*THEN GOTO +IF.*"java::B".*THEN GOTO +IF.*"java::E".*THEN GOTO IF.*"java::A".*THEN GOTO diff --git a/src/goto-programs/remove_virtual_functions.cpp b/src/goto-programs/remove_virtual_functions.cpp index f3b53c57a9b..86e19e7de81 100644 --- a/src/goto-programs/remove_virtual_functions.cpp +++ b/src/goto-programs/remove_virtual_functions.cpp @@ -445,10 +445,15 @@ void remove_virtual_functionst::get_functions( has_prefix( id2string(b.symbol_expr.get_identifier()), "java::java.lang.Object")) return true; - else if(a.symbol_expr.get_identifier() == b.symbol_expr.get_identifier()) - return a.class_id < b.class_id; else - return a.symbol_expr.get_identifier() < b.symbol_expr.get_identifier(); + { + int cmp = a.symbol_expr.get_identifier().compare( + b.symbol_expr.get_identifier()); + if(cmp == 0) + return a.class_id < b.class_id; + else + return cmp < 0; + } }); } From d102af95f1850d915b2622dd4f6524bbd1d67e70 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Tue, 24 Apr 2018 12:36:58 +0100 Subject: [PATCH 43/93] fix array->f typechecking --- regression/ansi-c/Struct_ptrmember1/main.c | 10 +++++++ regression/ansi-c/Struct_ptrmember1/test.desc | 8 +++++ src/ansi-c/c_typecheck_expr.cpp | 30 +++++++++++-------- 3 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 regression/ansi-c/Struct_ptrmember1/main.c create mode 100644 regression/ansi-c/Struct_ptrmember1/test.desc diff --git a/regression/ansi-c/Struct_ptrmember1/main.c b/regression/ansi-c/Struct_ptrmember1/main.c new file mode 100644 index 00000000000..b88cc5b8710 --- /dev/null +++ b/regression/ansi-c/Struct_ptrmember1/main.c @@ -0,0 +1,10 @@ +struct some_struct +{ + int some_field; +} array[10]; + +int main() +{ + array[0].some_field=1; + array->some_field=1; +} diff --git a/regression/ansi-c/Struct_ptrmember1/test.desc b/regression/ansi-c/Struct_ptrmember1/test.desc new file mode 100644 index 00000000000..466da18b2b5 --- /dev/null +++ b/regression/ansi-c/Struct_ptrmember1/test.desc @@ -0,0 +1,8 @@ +CORE +main.c + +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring +^CONVERSION ERROR$ diff --git a/src/ansi-c/c_typecheck_expr.cpp b/src/ansi-c/c_typecheck_expr.cpp index be300c00258..5a8eb6cfb4e 100644 --- a/src/ansi-c/c_typecheck_expr.cpp +++ b/src/ansi-c/c_typecheck_expr.cpp @@ -1431,25 +1431,31 @@ void c_typecheck_baset::typecheck_expr_ptrmember(exprt &expr) const typet &final_op0_type=follow(expr.op0().type()); - if(final_op0_type.id()!=ID_pointer && - final_op0_type.id()!=ID_array) + if(final_op0_type.id()==ID_array) + { + // a->f is the same as a[0].f + exprt zero=from_integer(0, index_type()); + index_exprt index_expr(expr.op0(), zero, final_op0_type.subtype()); + index_expr.set(ID_C_lvalue, true); + expr.op0().swap(index_expr); + } + else if(final_op0_type.id()==ID_pointer) + { + // turn x->y into (*x).y + dereference_exprt deref_expr(expr.op0()); + deref_expr.add_source_location()=expr.source_location(); + typecheck_expr_dereference(deref_expr); + expr.op0().swap(deref_expr); + } + else { err_location(expr); - error() << "ptrmember operator requires pointer type " + error() << "ptrmember operator requires pointer or array type " "on left hand side, but got `" << to_string(expr.op0().type()) << "'" << eom; throw 0; } - // turn x->y into (*x).y - - dereference_exprt deref(expr.op0()); - deref.add_source_location()=expr.source_location(); - - typecheck_expr_dereference(deref); - - expr.op0().swap(deref); - expr.id(ID_member); typecheck_expr_member(expr); } From 116067a0ce7934d72e94031488d6483516bd8ac9 Mon Sep 17 00:00:00 2001 From: thk123 Date: Thu, 19 Apr 2018 13:59:27 +0100 Subject: [PATCH 44/93] Extension to interpreter class --- src/goto-programs/interpreter_class.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/goto-programs/interpreter_class.h b/src/goto-programs/interpreter_class.h index b8e2e4cc437..ccc4730fba0 100644 --- a/src/goto-programs/interpreter_class.h +++ b/src/goto-programs/interpreter_class.h @@ -85,6 +85,7 @@ class interpretert:public messaget irep_idt calling_function; function_assignmentst return_assignments; function_assignmentst param_assignments; + function_assignmentst exception_assignments; }; // list_input_varst maps function identifiers onto a vector of [name = value] From 4ebd9ec6d139f03d33a230e522ad2eb5361c47af Mon Sep 17 00:00:00 2001 From: "Lukasz A.J. Wrona" Date: Tue, 24 Apr 2018 17:59:20 +0100 Subject: [PATCH 45/93] Update coding standard --- CODING_STANDARD.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CODING_STANDARD.md b/CODING_STANDARD.md index c5d67173e14..6fbe519b293 100644 --- a/CODING_STANDARD.md +++ b/CODING_STANDARD.md @@ -19,7 +19,9 @@ Formatting is enforced using clang-format. For more information about this, see - Nested function calls do not need to be broken up into separate lines even if the outer function call does. - If a method is bigger than 50 lines, break it into parts. -- Put matching `{ }` into the same column. +- Put matching `{ }` into the same column, except for lambdas, where you should + place `{` directly after the closing `)`. This rule also doesn't apply to + initializer lists. - Spaces around binary operators (`=`, `+`, `==` ...) - Space after comma (parameter lists, argument lists, ...) - Space after colon inside `for` From 1747dd30387f76c81d92b544b1d7199b862c2b36 Mon Sep 17 00:00:00 2001 From: "Lukasz A.J. Wrona" Date: Tue, 24 Apr 2018 17:59:38 +0100 Subject: [PATCH 46/93] Remove brace checking from cpplint --- scripts/cpplint.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/scripts/cpplint.py b/scripts/cpplint.py index bb08391f4d9..d01baeb2fcf 100755 --- a/scripts/cpplint.py +++ b/scripts/cpplint.py @@ -3972,14 +3972,6 @@ def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error): error(filename, linenum, 'whitespace/braces', 5, 'Missing space before {') - # Make sure '} else {' has spaces. - # if Search(r'}else', line): - # error(filename, linenum, 'whitespace/braces', 5, - # 'Missing space before else') - if (Search(r'^.*[^\s].*}$', line) or Search(r'^.*[^\s].*{$', line)) and not(Search(r'{[^}]*}', line)): - error(filename, linenum, 'whitespace/braces', 5, - 'Put braces on a separate next line') - # You shouldn't have a space before a semicolon at the end of the line. # There's a special case for "for" since the style guide allows space before # the semicolon there. From 313976d1afababa6cc7561eb6fd16ed3c8625667 Mon Sep 17 00:00:00 2001 From: "Lukasz A.J. Wrona" Date: Tue, 24 Apr 2018 17:59:54 +0100 Subject: [PATCH 47/93] Remove NOLINTs for lambdas. --- src/goto-programs/goto_convert.cpp | 6 +-- src/goto-programs/lazy_goto_model.h | 6 +-- src/goto-symex/symex_main.cpp | 4 +- src/java_bytecode/expr2java.h | 6 +-- .../java_bytecode_convert_method.cpp | 6 +-- .../java_bytecode_instrument.cpp | 2 +- src/java_bytecode/java_bytecode_language.cpp | 2 +- src/java_bytecode/remove_exceptions.cpp | 2 +- src/java_bytecode/remove_instanceof.cpp | 4 +- src/java_bytecode/replace_java_nondet.cpp | 4 +- src/jbmc/jbmc_parse_options.cpp | 25 +++++----- src/jsil/jsil_types.cpp | 46 ++++++------------- ...ng_constraint_generator_transformation.cpp | 6 +-- src/solvers/refinement/string_refinement.cpp | 8 ++-- src/util/graph.h | 11 ++--- .../inherited_static_fields.cpp | 11 ++--- .../instantiate_not_contains.cpp | 7 ++- .../string_refinement/dependency_graph.cpp | 6 +-- 18 files changed, 64 insertions(+), 98 deletions(-) diff --git a/src/goto-programs/goto_convert.cpp b/src/goto-programs/goto_convert.cpp index 2bca47c7723..453679bc639 100644 --- a/src/goto-programs/goto_convert.cpp +++ b/src/goto-programs/goto_convert.cpp @@ -1823,10 +1823,8 @@ void goto_convertt::generate_ifthenelse( // Note this depends on the fact that `instructions` is a std::list // and so goto-program-destructive-append preserves iterator validity. if(is_guarded_goto) - guarded_gotos.push_back({ // NOLINT(whitespace/braces) - tmp_v.instructions.begin(), - tmp_w.instructions.begin(), - guard}); + guarded_gotos.push_back( + {tmp_v.instructions.begin(), tmp_w.instructions.begin(), guard}); dest.destructive_append(tmp_v); dest.destructive_append(tmp_w); diff --git a/src/goto-programs/lazy_goto_model.h b/src/goto-programs/lazy_goto_model.h index 78b078cadc2..417115024ce 100644 --- a/src/goto-programs/lazy_goto_model.h +++ b/src/goto-programs/lazy_goto_model.h @@ -53,11 +53,11 @@ class lazy_goto_modelt : public abstract_goto_modelt message_handlert &message_handler) { return lazy_goto_modelt( - [&handler, &options] - (goto_model_functiont &fun, const abstract_goto_modelt &model) { // NOLINT(*) + [&handler, + &options](goto_model_functiont &fun, const abstract_goto_modelt &model) { handler.process_goto_function(fun, model, options); }, - [&handler, &options] (goto_modelt &goto_model) -> bool { // NOLINT(*) + [&handler, &options](goto_modelt &goto_model) -> bool { return handler.process_goto_functions(goto_model, options); }, message_handler); diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp index 0a45365c296..97c2c127c22 100644 --- a/src/goto-symex/symex_main.cpp +++ b/src/goto-symex/symex_main.cpp @@ -166,8 +166,8 @@ void goto_symext::symex_threaded_step( static goto_symext::get_goto_functiont get_function_from_goto_functions( const goto_functionst &goto_functions) { - return [&goto_functions](const irep_idt &key) -> - const goto_functionst::goto_functiont & { // NOLINT(*) + return [&goto_functions]( + const irep_idt &key) -> const goto_functionst::goto_functiont & { return goto_functions.function_map.at(key); }; } diff --git a/src/java_bytecode/expr2java.h b/src/java_bytecode/expr2java.h index 2adb417eb03..1df94bdc9ce 100644 --- a/src/java_bytecode/expr2java.h +++ b/src/java_bytecode/expr2java.h @@ -66,7 +66,7 @@ std::string floating_point_to_java_string(float_type value) return class_name + ".POSITIVE_INFINITY"; if(std::isinf(value) && value <= 0.) return class_name + ".NEGATIVE_INFINITY"; - const std::string decimal = [&]() -> std::string { // NOLINT + const std::string decimal = [&]() -> std::string { // Using ostringstream instead of to_string to get string without // trailing zeros std::ostringstream raw_stream; @@ -76,7 +76,7 @@ std::string floating_point_to_java_string(float_type value) return raw_decimal + ".0"; return raw_decimal; }(); - const bool is_lossless = [&] { // NOLINT + const bool is_lossless = [&] { if(value == std::numeric_limits::min()) return true; try @@ -88,7 +88,7 @@ std::string floating_point_to_java_string(float_type value) return false; } }(); - const std::string lossless = [&]() -> std::string { // NOLINT + const std::string lossless = [&]() -> std::string { if(is_lossless) return decimal; std::ostringstream stream; diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp index cdc75bad6dd..9b221d4298c 100644 --- a/src/java_bytecode/java_bytecode_convert_method.cpp +++ b/src/java_bytecode/java_bytecode_convert_method.cpp @@ -895,10 +895,8 @@ static void gather_symbol_live_ranges( if(e.id()==ID_symbol) { const auto &symexpr=to_symbol_expr(e); - auto findit= - result.insert({ // NOLINT(whitespace/braces) - symexpr.get_identifier(), - java_bytecode_convert_methodt::variablet()}); + auto findit = result.insert( + {symexpr.get_identifier(), java_bytecode_convert_methodt::variablet()}); auto &var=findit.first->second; if(findit.second) { diff --git a/src/java_bytecode/java_bytecode_instrument.cpp b/src/java_bytecode/java_bytecode_instrument.cpp index 7c09b07b2fe..bd2e6a95be4 100644 --- a/src/java_bytecode/java_bytecode_instrument.cpp +++ b/src/java_bytecode/java_bytecode_instrument.cpp @@ -75,7 +75,7 @@ class java_bytecode_instrumentt:public messaget optionalt instrument_expr(const exprt &expr); }; -const std::vector exception_needed_classes = { // NOLINT +const std::vector exception_needed_classes = { "java.lang.ArithmeticException", "java.lang.ArrayIndexOutOfBoundsException", "java.lang.ClassCastException", diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index 967113657ce..cfcb797cc40 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -161,7 +161,7 @@ bool java_bytecode_languaget::parse( { string_preprocess.initialize_known_type_table(); - auto get_string_base_classes = [this](const irep_idt &id) { // NOLINT (*) + auto get_string_base_classes = [this](const irep_idt &id) { return string_preprocess.get_string_type_base_classes(id); }; diff --git a/src/java_bytecode/remove_exceptions.cpp b/src/java_bytecode/remove_exceptions.cpp index 618c1a8cda1..9b6801128c2 100644 --- a/src/java_bytecode/remove_exceptions.cpp +++ b/src/java_bytecode/remove_exceptions.cpp @@ -572,7 +572,7 @@ void remove_exceptions( std::map> exceptions_map; uncaught_exceptions(goto_functions, ns, exceptions_map); remove_exceptionst::function_may_throwt function_may_throw = - [&exceptions_map](const irep_idt &id) { // NOLINT(whitespace/braces) + [&exceptions_map](const irep_idt &id) { return !exceptions_map[id].empty(); }; remove_exceptionst remove_exceptions( diff --git a/src/java_bytecode/remove_instanceof.cpp b/src/java_bytecode/remove_instanceof.cpp index 37cb8cc3094..cb93fcbbb98 100644 --- a/src/java_bytecode/remove_instanceof.cpp +++ b/src/java_bytecode/remove_instanceof.cpp @@ -90,9 +90,7 @@ std::size_t remove_instanceoft::lower_instanceof( // Sort alphabetically to make order of generated disjuncts // independent of class loading order std::sort( - children.begin(), - children.end(), - [](const irep_idt &a, const irep_idt &b) { // NOLINT + children.begin(), children.end(), [](const irep_idt &a, const irep_idt &b) { return a.compare(b) < 0; }); diff --git a/src/java_bytecode/replace_java_nondet.cpp b/src/java_bytecode/replace_java_nondet.cpp index 264de82328b..6d0e23210c1 100644 --- a/src/java_bytecode/replace_java_nondet.cpp +++ b/src/java_bytecode/replace_java_nondet.cpp @@ -249,9 +249,7 @@ static goto_programt::targett check_and_replace_target( "goto_program missing END_FUNCTION instruction"); std::for_each( - target, - after_matching_assignment, - [](goto_programt::instructiont &instr) { // NOLINT (*) + target, after_matching_assignment, [](goto_programt::instructiont &instr) { instr.make_skip(); }); diff --git a/src/jbmc/jbmc_parse_options.cpp b/src/jbmc/jbmc_parse_options.cpp index 0a80a382b94..4a371001851 100644 --- a/src/jbmc/jbmc_parse_options.cpp +++ b/src/jbmc/jbmc_parse_options.cpp @@ -493,13 +493,13 @@ int jbmc_parse_optionst::doit() std::function configure_bmc = nullptr; if(options.get_bool_option("java-unwind-enum-static")) { - configure_bmc = []( - bmct &bmc, const symbol_tablet &symbol_table) { // NOLINT (*) - bmc.add_loop_unwind_handler([&symbol_table]( - const irep_idt &function_id, - unsigned loop_number, - unsigned unwind, - unsigned &max_unwind) { // NOLINT (*) + configure_bmc = [](bmct &bmc, const symbol_tablet &symbol_table) { + bmc.add_loop_unwind_handler( + [&symbol_table]( + const irep_idt &function_id, + unsigned loop_number, + unsigned unwind, + unsigned &max_unwind) { return java_enum_static_init_unwind_handler( function_id, loop_number, @@ -564,7 +564,7 @@ int jbmc_parse_optionst::doit() // executes. If --paths is active, these dump routines run after every // paths iteration. Its return value indicates that if we ran any dump // function, then we should skip the actual solver phase. - auto callback_after_symex = [this, &lazy_goto_model]() { // NOLINT (*) + auto callback_after_symex = [this, &lazy_goto_model]() { return show_loaded_functions(lazy_goto_model); }; @@ -729,11 +729,10 @@ void jbmc_parse_optionst::process_goto_function( remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF); } - auto function_is_stub = - [&symbol_table, &model](const irep_idt &id) { // NOLINT(*) - return symbol_table.lookup_ref(id).value.is_nil() && - !model.can_produce_function(id); - }; + auto function_is_stub = [&symbol_table, &model](const irep_idt &id) { + return symbol_table.lookup_ref(id).value.is_nil() && + !model.can_produce_function(id); + }; remove_returns(function, function_is_stub); diff --git a/src/jsil/jsil_types.cpp b/src/jsil/jsil_types.cpp index 12a76787149..ac2ff75c487 100644 --- a/src/jsil/jsil_types.cpp +++ b/src/jsil/jsil_types.cpp @@ -15,54 +15,38 @@ Author: Daiva Naudziuniene, daivan@amazon.com typet jsil_any_type() { - return jsil_union_typet({ // NOLINT(whitespace/braces) - jsil_empty_type(), - jsil_reference_type(), - jsil_value_type() - }); + return jsil_union_typet( + {jsil_empty_type(), jsil_reference_type(), jsil_value_type()}); } typet jsil_value_or_empty_type() { - return jsil_union_typet({ // NOLINT(whitespace/braces) - jsil_value_type(), - jsil_empty_type() - }); + return jsil_union_typet({jsil_value_type(), jsil_empty_type()}); } typet jsil_value_or_reference_type() { - return jsil_union_typet({ // NOLINT(whitespace/braces) - jsil_value_type(), - jsil_reference_type() - }); + return jsil_union_typet({jsil_value_type(), jsil_reference_type()}); } typet jsil_value_type() { - return jsil_union_typet({ // NOLINT(whitespace/braces) - jsil_undefined_type(), - jsil_null_type(), - jsil_prim_type(), - jsil_object_type() - }); + return jsil_union_typet( + {jsil_undefined_type(), + jsil_null_type(), + jsil_prim_type(), + jsil_object_type()}); } typet jsil_prim_type() { - return jsil_union_typet({ // NOLINT(whitespace/braces) - floatbv_typet(), - string_typet(), - bool_typet() - }); + return jsil_union_typet({floatbv_typet(), string_typet(), bool_typet()}); } typet jsil_reference_type() { - return jsil_union_typet({ // NOLINT(whitespace/braces) - jsil_member_reference_type(), - jsil_variable_reference_type() - }); + return jsil_union_typet( + {jsil_member_reference_type(), jsil_variable_reference_type()}); } typet jsil_member_reference_type() @@ -77,10 +61,8 @@ typet jsil_variable_reference_type() typet jsil_object_type() { - return jsil_union_typet({ // NOLINT(whitespace/braces) - jsil_user_object_type(), - jsil_builtin_object_type() - }); + return jsil_union_typet( + {jsil_user_object_type(), jsil_builtin_object_type()}); } typet jsil_user_object_type() diff --git a/src/solvers/refinement/string_constraint_generator_transformation.cpp b/src/solvers/refinement/string_constraint_generator_transformation.cpp index 154e027a5ef..effcef775e6 100644 --- a/src/solvers/refinement/string_constraint_generator_transformation.cpp +++ b/src/solvers/refinement/string_constraint_generator_transformation.cpp @@ -128,7 +128,7 @@ exprt string_constraint_generatort::add_axioms_for_substring( lemmas.push_back(equal_exprt(res.length(), minus_exprt(end1, start1))); // Axiom 2. - constraints.push_back([&] { // NOLINT + constraints.push_back([&] { const symbol_exprt idx = fresh_univ_index("QA_index_substring", index_type); return string_constraintt( idx, res.length(), equal_exprt(res[idx], str[plus_exprt(start1, idx)])); @@ -197,7 +197,7 @@ exprt string_constraint_generatort::add_axioms_for_trim( constraints.push_back(a6); // Axiom 7. - constraints.push_back([&] { // NOLINT + constraints.push_back([&] { const symbol_exprt n2 = fresh_univ_index("QA_index_trim2", index_type); const minus_exprt bound(minus_exprt(str.length(), idx), res.length()); const binary_relation_exprt eqn2( @@ -473,7 +473,7 @@ exprt string_constraint_generatort::add_axioms_for_replace( char_array_of_pointer(f.arguments()[1], f.arguments()[0]); if( const auto maybe_chars = - to_char_pair(f.arguments()[3], f.arguments()[4], [this](const exprt &e) { // NOLINT + to_char_pair(f.arguments()[3], f.arguments()[4], [this](const exprt &e) { return get_string_expr(e); })) { diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index 7a080dd361a..4fe87dfc7cb 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -696,7 +696,7 @@ decision_proceduret::resultt string_refinementt::dec_solve() constraints.begin(), constraints.end(), std::back_inserter(axioms.universal), - [&](string_constraintt constraint) { // NOLINT + [&](string_constraintt constraint) { symbol_resolve.replace_expr(constraint); DATA_INVARIANT( is_valid_string_constraint(error(), ns, constraint), @@ -711,14 +711,14 @@ decision_proceduret::resultt string_refinementt::dec_solve() not_contains_constraints.begin(), not_contains_constraints.end(), std::back_inserter(axioms.not_contains), - [&](string_not_contains_constraintt axiom) { // NOLINT + [&](string_not_contains_constraintt axiom) { symbol_resolve.replace_expr(axiom); return axiom; }); for(const auto &nc_axiom : axioms.not_contains) { - const auto &witness_type = [&] { // NOLINT + const auto &witness_type = [&] { const auto &rtype = to_array_type(nc_axiom.s0().type()); const typet &index_type = rtype.size().type(); return array_typet(index_type, infinity_exprt(index_type)); @@ -1928,7 +1928,7 @@ static void update_index_set( static optionalt find_index(const exprt &expr, const exprt &str, const symbol_exprt &qvar) { - auto index_str_containing_qvar = [&](const exprt &e) { // NOLINT + auto index_str_containing_qvar = [&](const exprt &e) { if(auto index_expr = expr_try_dynamic_cast(e)) { const auto &arr = index_expr->array(); diff --git a/src/util/graph.h b/src/util/graph.h index 45530f09ef6..16af29ea634 100644 --- a/src/util/graph.h +++ b/src/util/graph.h @@ -486,7 +486,7 @@ void get_reachable( { auto n = stack.back(); stack.pop_back(); - for_each_successor(n, [&](const nodet &node) { // NOLINT + for_each_successor(n, [&](const nodet &node) { if(set.insert(node).second) stack.push_back(node); }); @@ -749,8 +749,8 @@ void output_dot_generic( &for_each_succ, const std::function node_to_string) { - for_each_node([&](const node_index_type &i) { // NOLINT - for_each_succ(i, [&](const node_index_type &n) { // NOLINT + for_each_node([&](const node_index_type &i) { + for_each_succ(i, [&](const node_index_type &n) { out << node_to_string(i) << " -> " << node_to_string(n) << '\n'; }); }); @@ -784,14 +784,13 @@ template void grapht::output_dot(std::ostream &out) const { const auto for_each_node = - [&](const std::function &f) { // NOLINT + [&](const std::function &f) { for(node_indext i = 0; i < nodes.size(); ++i) f(i); }; const auto for_each_succ = [&]( - const node_indext &i, - const std::function &f) { // NOLINT + const node_indext &i, const std::function &f) { for_each_successor(i, f); }; diff --git a/unit/java_bytecode/inherited_static_fields/inherited_static_fields.cpp b/unit/java_bytecode/inherited_static_fields/inherited_static_fields.cpp index 1341c158176..16fb06aec81 100644 --- a/unit/java_bytecode/inherited_static_fields/inherited_static_fields.cpp +++ b/unit/java_bytecode/inherited_static_fields/inherited_static_fields.cpp @@ -19,13 +19,10 @@ /// \return true if a suitable symbol_exprt is found static bool contains_symbol_reference(const exprt &expr, const irep_idt &id) { - return - std::any_of( - expr.depth_begin(), - expr.depth_end(), - [id](const exprt &e) { // NOLINT (*) - return e.id() == ID_symbol && to_symbol_expr(e).get_identifier() == id; - }); + return std::any_of( + expr.depth_begin(), expr.depth_end(), [id](const exprt &e) { + return e.id() == ID_symbol && to_symbol_expr(e).get_identifier() == id; + }); } SCENARIO( diff --git a/unit/solvers/refinement/string_constraint_instantiation/instantiate_not_contains.cpp b/unit/solvers/refinement/string_constraint_instantiation/instantiate_not_contains.cpp index db6e28193c4..7e6773e50c0 100644 --- a/unit/solvers/refinement/string_constraint_instantiation/instantiate_not_contains.cpp +++ b/unit/solvers/refinement/string_constraint_instantiation/instantiate_not_contains.cpp @@ -205,7 +205,7 @@ SCENARIO("instantiate_not_contains", constraints.begin(), constraints.end(), axioms, - [&](const std::string &accu, string_constraintt sc) { // NOLINT + [&](const std::string &accu, string_constraintt sc) { simplify(sc, ns); std::string s; java_lang->from_expr(sc, s, ns); @@ -217,8 +217,7 @@ SCENARIO("instantiate_not_contains", nc_contraints.begin(), nc_contraints.end(), axioms, - [&]( - const std::string &accu, string_not_contains_constraintt sc) { // NOLINT + [&](const std::string &accu, string_not_contains_constraintt sc) { simplify(sc, ns); generator.witness[sc] = generator.fresh_symbol("w", t.witness_type()); nc_axioms.push_back(sc); @@ -232,7 +231,7 @@ SCENARIO("instantiate_not_contains", lemmas.begin(), lemmas.end(), axioms, - [&](const std::string &accu, exprt axiom) { // NOLINT + [&](const std::string &accu, exprt axiom) { simplify(axiom, ns); std::string s; java_lang->from_expr(axiom, s, ns); diff --git a/unit/solvers/refinement/string_refinement/dependency_graph.cpp b/unit/solvers/refinement/string_refinement/dependency_graph.cpp index 3a0b6e16b62..de6bd2d69e6 100644 --- a/unit/solvers/refinement/string_refinement/dependency_graph.cpp +++ b/unit/solvers/refinement/string_refinement/dependency_graph.cpp @@ -142,8 +142,7 @@ SCENARIO("dependency_graph", "[core][solvers][refinement][string_refinement]") const auto &node = dependencies.get_node(char_array3); std::size_t nb_dependencies = 0; dependencies.for_each_dependency( - node, - [&](const string_dependenciest::builtin_function_nodet &n) { // NOLINT + node, [&](const string_dependenciest::builtin_function_nodet &n) { nb_dependencies++; THEN("primitive0 depends on string1 and string2") { @@ -161,8 +160,7 @@ SCENARIO("dependency_graph", "[core][solvers][refinement][string_refinement]") const auto &node = dependencies.get_node(char_array5); std::size_t nb_dependencies = 0; dependencies.for_each_dependency( - node, - [&](const string_dependenciest::builtin_function_nodet &n) { // NOLINT + node, [&](const string_dependenciest::builtin_function_nodet &n) { nb_dependencies++; THEN("primitive1 depends on string3 and string4") { From 2a7cee9028db265cd1b5063790b12fa9b00053a3 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Tue, 24 Apr 2018 21:56:20 +0100 Subject: [PATCH 48/93] show java_new_array_data side effects --- src/java_bytecode/expr2java.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/java_bytecode/expr2java.cpp b/src/java_bytecode/expr2java.cpp index 51bb43ad82b..8bbd9b093c5 100644 --- a/src/java_bytecode/expr2java.cpp +++ b/src/java_bytecode/expr2java.cpp @@ -350,7 +350,8 @@ std::string expr2javat::convert_java_new( { std::string dest; - if(src.get(ID_statement)==ID_java_new_array) + if(src.get(ID_statement)==ID_java_new_array || + src.get(ID_statement)==ID_java_new_array_data) { dest="new"; @@ -398,7 +399,8 @@ std::string expr2javat::convert_with_precedence( return convert_java_instanceof(src, precedence=15); else if(src.id()==ID_side_effect && (src.get(ID_statement)==ID_java_new || - src.get(ID_statement)==ID_java_new_array)) + src.get(ID_statement)==ID_java_new_array || + src.get(ID_statement)==ID_java_new_array_data)) return convert_java_new(src, precedence=15); else if(src.id()==ID_side_effect && src.get(ID_statement)==ID_throw) From ec6769dd43d0c1eb2e10ee6723a9ed18827e941d Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 21 Apr 2018 22:27:24 +0100 Subject: [PATCH 49/93] Replace asserts by invariants --- .../java_bytecode_typecheck_type.cpp | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/java_bytecode/java_bytecode_typecheck_type.cpp b/src/java_bytecode/java_bytecode_typecheck_type.cpp index 79fb175db96..2f26feb59bc 100644 --- a/src/java_bytecode/java_bytecode_typecheck_type.cpp +++ b/src/java_bytecode/java_bytecode_typecheck_type.cpp @@ -11,6 +11,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_bytecode_typecheck.h" +#include #include void java_bytecode_typecheckt::typecheck_type(typet &type) @@ -19,17 +20,12 @@ void java_bytecode_typecheckt::typecheck_type(typet &type) { irep_idt identifier=to_symbol_type(type).get_identifier(); - symbol_tablet::symbolst::const_iterator s_it= - symbol_table.symbols.find(identifier); - - // must exist already in the symbol table - if(s_it==symbol_table.symbols.end()) - { - error() << "failed to find type symbol "<< identifier << eom; - throw 0; - } - - assert(s_it->second.is_type); + auto type_symbol = symbol_table.lookup(identifier); + DATA_INVARIANT( + type_symbol, "symbol " + id2string(identifier) + " must exist already"); + DATA_INVARIANT( + type_symbol->is_type, + "symbol " + id2string(identifier) + " must be a type"); } else if(type.id()==ID_pointer) { @@ -55,7 +51,8 @@ void java_bytecode_typecheckt::typecheck_type(typet &type) void java_bytecode_typecheckt::typecheck_type_symbol(symbolt &symbol) { - assert(symbol.is_type); + DATA_INVARIANT( + symbol.is_type, "symbol " + id2string(symbol.name) + " must be a type"); symbol.mode = ID_java; typecheck_type(symbol.type); From 9ad4b3c5a0cf5c9521b6cc4008ff0be5037a0d21 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 21 Apr 2018 22:29:08 +0100 Subject: [PATCH 50/93] Set mode in goto_convert auxiliary symbols --- src/goto-programs/builtin_functions.cpp | 27 +++++++++---------- src/goto-programs/goto_clean_expr.cpp | 4 +-- src/goto-programs/goto_convert.cpp | 22 +++++++-------- src/goto-programs/goto_convert_class.h | 3 ++- .../goto_convert_side_effect.cpp | 14 +++++----- 5 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/goto-programs/builtin_functions.cpp b/src/goto-programs/builtin_functions.cpp index 8780e092575..666c463bee9 100644 --- a/src/goto-programs/builtin_functions.cpp +++ b/src/goto-programs/builtin_functions.cpp @@ -468,8 +468,8 @@ void goto_convertt::do_cpp_new( assert(code_type.parameters().size()==1 || code_type.parameters().size()==2); - const symbolt &tmp_symbol= - new_tmp_symbol(return_type, "new", dest, rhs.source_location()); + const symbolt &tmp_symbol = + new_tmp_symbol(return_type, "new", dest, rhs.source_location(), ID_cpp); tmp_symbol_expr=tmp_symbol.symbol_expr(); @@ -499,8 +499,8 @@ void goto_convertt::do_cpp_new( assert(code_type.parameters().size()==2 || code_type.parameters().size()==3); - const symbolt &tmp_symbol= - new_tmp_symbol(return_type, "new", dest, rhs.source_location()); + const symbolt &tmp_symbol = + new_tmp_symbol(return_type, "new", dest, rhs.source_location(), ID_cpp); tmp_symbol_expr=tmp_symbol.symbol_expr(); @@ -663,13 +663,10 @@ void goto_convertt::do_java_new_array( // Must directly assign the new array to a temporary // because goto-symex will notice `x=side_effect_exprt` but not // `x=typecast_exprt(side_effect_exprt(...))` - symbol_exprt new_array_data_symbol= + symbol_exprt new_array_data_symbol = new_tmp_symbol( - data_java_new_expr.type(), - "new_array_data", - dest, - location) - .symbol_expr(); + data_java_new_expr.type(), "new_array_data", dest, location, ID_java) + .symbol_expr(); goto_programt::targett t_p2=dest.add_instruction(ASSIGN); t_p2->code=code_assignt(new_array_data_symbol, data_java_new_expr); t_p2->source_location=location; @@ -707,8 +704,9 @@ void goto_convertt::do_java_new_array( goto_programt tmp; - symbol_exprt tmp_i= - new_tmp_symbol(length.type(), "index", tmp, location).symbol_expr(); + symbol_exprt tmp_i = + new_tmp_symbol(length.type(), "index", tmp, location, ID_java) + .symbol_expr(); code_fort for_loop; @@ -730,8 +728,9 @@ void goto_convertt::do_java_new_array( plus_exprt(data, tmp_i), data.type().subtype()); code_blockt for_body; - symbol_exprt init_sym= - new_tmp_symbol(sub_type, "subarray_init", tmp, location).symbol_expr(); + symbol_exprt init_sym = + new_tmp_symbol(sub_type, "subarray_init", tmp, location, ID_java) + .symbol_expr(); code_assignt init_subarray(init_sym, sub_java_new); code_assignt assign_subarray( diff --git a/src/goto-programs/goto_clean_expr.cpp b/src/goto-programs/goto_clean_expr.cpp index 8c82a34a582..0660f80335f 100644 --- a/src/goto-programs/goto_clean_expr.cpp +++ b/src/goto-programs/goto_clean_expr.cpp @@ -237,8 +237,8 @@ void goto_convertt::clean_expr( if(result_is_used) { - symbolt &new_symbol= - new_tmp_symbol(expr.type(), "if_expr", dest, source_location); + symbolt &new_symbol = new_tmp_symbol( + expr.type(), "if_expr", dest, source_location, expr.get(ID_mode)); code_assignt assignment_true; assignment_true.lhs()=new_symbol.symbol_expr(); diff --git a/src/goto-programs/goto_convert.cpp b/src/goto-programs/goto_convert.cpp index 453679bc639..b8ad4465554 100644 --- a/src/goto-programs/goto_convert.cpp +++ b/src/goto-programs/goto_convert.cpp @@ -2053,16 +2053,16 @@ symbolt &goto_convertt::new_tmp_symbol( const typet &type, const std::string &suffix, goto_programt &dest, - const source_locationt &source_location) + const source_locationt &source_location, + const irep_idt &mode) { - symbolt &new_symbol= - get_fresh_aux_symbol( - type, - tmp_symbol_prefix, - "tmp_"+suffix, - source_location, - irep_idt(), - symbol_table); + symbolt &new_symbol = get_fresh_aux_symbol( + type, + tmp_symbol_prefix, + "tmp_" + suffix, + source_location, + mode, + symbol_table); code_declt decl; decl.symbol()=new_symbol.symbol_expr(); @@ -2079,8 +2079,8 @@ void goto_convertt::make_temp_symbol( { const source_locationt source_location=expr.find_source_location(); - symbolt &new_symbol= - new_tmp_symbol(expr.type(), suffix, dest, source_location); + symbolt &new_symbol = new_tmp_symbol( + expr.type(), suffix, dest, source_location, expr.get(ID_mode)); code_assignt assignment; assignment.lhs()=new_symbol.symbol_expr(); diff --git a/src/goto-programs/goto_convert_class.h b/src/goto-programs/goto_convert_class.h index e74833815c4..84a90cb59cf 100644 --- a/src/goto-programs/goto_convert_class.h +++ b/src/goto-programs/goto_convert_class.h @@ -59,7 +59,8 @@ class goto_convertt:public messaget const typet &type, const std::string &suffix, goto_programt &dest, - const source_locationt &); + const source_locationt &, + const irep_idt &mode); symbol_exprt make_compound_literal( const exprt &expr, diff --git a/src/goto-programs/goto_convert_side_effect.cpp b/src/goto-programs/goto_convert_side_effect.cpp index bec761420ca..def8d98b170 100644 --- a/src/goto-programs/goto_convert_side_effect.cpp +++ b/src/goto-programs/goto_convert_side_effect.cpp @@ -522,10 +522,8 @@ void goto_convertt::remove_temporary_object( throw 0; } - symbolt &new_symbol= - new_tmp_symbol(expr.type(), "obj", dest, expr.find_source_location()); - - new_symbol.mode=expr.get(ID_mode); + symbolt &new_symbol = new_tmp_symbol( + expr.type(), "obj", dest, expr.find_source_location(), expr.get(ID_mode)); if(expr.operands().size()==1) { @@ -599,8 +597,12 @@ void goto_convertt::remove_statement_expression( source_locationt source_location=last.find_source_location(); - symbolt &new_symbol= - new_tmp_symbol(expr.type(), "statement_expression", dest, source_location); + symbolt &new_symbol = new_tmp_symbol( + expr.type(), + "statement_expression", + dest, + source_location, + expr.get(ID_mode)); symbol_exprt tmp_symbol_expr(new_symbol.name, new_symbol.type); tmp_symbol_expr.add_source_location()=source_location; From 37ff9ebef89ccf27fbeba844499e7105c1296a77 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 21 Apr 2018 22:30:30 +0100 Subject: [PATCH 51/93] Bugfix: use proper language registration in unit tests --- unit/testing-utils/load_java_class.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/unit/testing-utils/load_java_class.cpp b/unit/testing-utils/load_java_class.cpp index f198008dff4..217a3bb25d7 100644 --- a/unit/testing-utils/load_java_class.cpp +++ b/unit/testing-utils/load_java_class.cpp @@ -16,6 +16,8 @@ #include +#include + #include #include @@ -37,11 +39,13 @@ symbol_tablet load_java_class_lazy( free_form_cmdlinet lazy_command_line; lazy_command_line.add_flag("lazy-methods"); + register_language(new_java_bytecode_language); + return load_java_class( java_class_name, class_path, main, - new_java_bytecode_language(), + get_language_from_mode(ID_java), lazy_command_line); } @@ -59,8 +63,10 @@ symbol_tablet load_java_class( const std::string &class_path, const std::string &main) { + register_language(new_java_bytecode_language); + return load_java_class( - java_class_name, class_path, main, new_java_bytecode_language()); + java_class_name, class_path, main, get_language_from_mode(ID_java)); } /// Go through the process of loading, type-checking and finalising loading a From 42807204d9e8dac7d9b06a7992d091686537a4ae Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 21 Apr 2018 22:31:59 +0100 Subject: [PATCH 52/93] Associate dynamic objects with respective language mode --- src/goto-symex/symex_builtin_functions.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/goto-symex/symex_builtin_functions.cpp b/src/goto-symex/symex_builtin_functions.cpp index c000c3c5c0f..1a7ba984e82 100644 --- a/src/goto-symex/symex_builtin_functions.cpp +++ b/src/goto-symex/symex_builtin_functions.cpp @@ -66,6 +66,9 @@ void goto_symext::symex_allocate( exprt size=code.op0(); typet object_type=nil_typet(); + auto function_symbol = outer_symbol_table.lookup(state.source.pc->function); + INVARIANT(function_symbol, "function associated with instruction not found"); + const irep_idt &mode = function_symbol->mode; // is the type given? if(code.type().id()==ID_pointer && code.type().subtype().id()!=ID_empty) @@ -142,7 +145,7 @@ void goto_symext::symex_allocate( size_symbol.name="symex_dynamic::"+id2string(size_symbol.base_name); size_symbol.is_lvalue=true; size_symbol.type=tmp_size.type(); - size_symbol.mode=ID_C; + size_symbol.mode = mode; state.symbol_table.add(size_symbol); @@ -161,7 +164,7 @@ void goto_symext::symex_allocate( value_symbol.is_lvalue=true; value_symbol.type=object_type; value_symbol.type.set("#dynamic", true); - value_symbol.mode=ID_C; + value_symbol.mode = mode; state.symbol_table.add(value_symbol); From 7b3699e24d79fac583c43c8f5abfcbf18485e307 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Tue, 24 Apr 2018 21:38:24 +0100 Subject: [PATCH 53/93] allow address_of of byte_extract expressions --- src/solvers/flattening/bv_pointers.cpp | 27 ++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/solvers/flattening/bv_pointers.cpp b/src/solvers/flattening/bv_pointers.cpp index 5833a3e4549..b82a54ac615 100644 --- a/src/solvers/flattening/bv_pointers.cpp +++ b/src/solvers/flattening/bv_pointers.cpp @@ -136,7 +136,7 @@ bool bv_pointerst::convert_address_of_rec( { // this should be gone bv=convert_pointer_type(array); - POSTCONDITION(bv.size()==bits); + CHECK_RETURN(bv.size()==bits); } else if(array_type.id()==ID_array || array_type.id()==ID_incomplete_array || @@ -144,7 +144,7 @@ bool bv_pointerst::convert_address_of_rec( { if(convert_address_of_rec(array, bv)) return true; - POSTCONDITION(bv.size()==bits); + CHECK_RETURN(bv.size()==bits); } else UNREACHABLE; @@ -155,7 +155,22 @@ bool bv_pointerst::convert_address_of_rec( DATA_INVARIANT(size>0, "array subtype expected to have non-zero size"); offset_arithmetic(bv, size, index); - POSTCONDITION(bv.size()==bits); + CHECK_RETURN(bv.size()==bits); + return false; + } + else if(expr.id()==ID_byte_extract_little_endian || + expr.id()==ID_byte_extract_big_endian) + { + const auto &byte_extract_expr=to_byte_extract_expr(expr); + + // recursive call + if(convert_address_of_rec(byte_extract_expr.op(), bv)) + return true; + + CHECK_RETURN(bv.size()==bits); + + offset_arithmetic(bv, 1, byte_extract_expr.offset()); + CHECK_RETURN(bv.size()==bits); return false; } else if(expr.id()==ID_member) @@ -296,7 +311,7 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr) return bv; } - POSTCONDITION(bv.size()==bits); + CHECK_RETURN(bv.size()==bits); return bv; } else if(expr.id()==ID_constant) @@ -334,13 +349,13 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr) { count++; bv=convert_bv(*it); - POSTCONDITION(bv.size()==bits); + CHECK_RETURN(bv.size()==bits); typet pointer_sub_type=it->type().subtype(); if(pointer_sub_type.id()==ID_empty) pointer_sub_type=char_type(); size=pointer_offset_size(pointer_sub_type, ns); - POSTCONDITION(size>0); + CHECK_RETURN(size>0); } } From ae95559bd3242cdbd41b8fd6870e27b1023d8b1b Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Wed, 25 Apr 2018 08:49:46 +0100 Subject: [PATCH 54/93] Remove unused symbolt::{to,from}_irep Serialisation is done in write_goto_binary_v3 and read_bin_goto_object_v3. --- src/util/symbol.cpp | 80 --------------------------------------------- src/util/symbol.h | 4 --- 2 files changed, 84 deletions(-) diff --git a/src/util/symbol.cpp b/src/util/symbol.cpp index 652fe422c56..95676c17dfc 100644 --- a/src/util/symbol.cpp +++ b/src/util/symbol.cpp @@ -73,86 +73,6 @@ std::ostream &operator<<(std::ostream &out, return out; } -irept symbolt::to_irep() const -{ - irept dest; - - dest.clear(); - dest.add(ID_type)=type; - dest.add(ID_value)=value; - dest.add(ID_location)=location; - dest.set(ID_name, name); - dest.set(ID_module, module); - dest.set(ID_base_name, base_name); - dest.set(ID_mode, mode); - dest.set(ID_pretty_name, pretty_name); - - if(is_type) - dest.set("is_type", true); - if(is_macro) - dest.set("is_macro", true); - if(is_exported) - dest.set("is_exported", true); - if(is_input) - dest.set("is_input", true); - if(is_output) - dest.set("is_output", true); - if(is_state_var) - dest.set("is_statevar", true); - if(is_parameter) - dest.set("is_parameter", true); - if(is_auxiliary) - dest.set("is_auxiliary", true); - if(is_weak) - dest.set("is_weak", true); - if(is_property) - dest.set("is_property", true); - if(is_lvalue) - dest.set("is_lvalue", true); - if(is_static_lifetime) - dest.set("is_static_lifetime", true); - if(is_thread_local) - dest.set("is_thread_local", true); - if(is_file_local) - dest.set("is_file_local", true); - if(is_extern) - dest.set("is_extern", true); - if(is_volatile) - dest.set("is_volatile", true); - - return dest; -} - -void symbolt::from_irep(const irept &src) -{ - type=static_cast(src.find(ID_type)); - value=static_cast(src.find(ID_value)); - location=static_cast(src.find(ID_location)); - - name=src.get(ID_name); - module=src.get(ID_module); - base_name=src.get(ID_base_name); - mode=src.get(ID_mode); - pretty_name=src.get(ID_pretty_name); - - is_type=src.get_bool("is_type"); - is_macro=src.get_bool("is_macro"); - is_exported=src.get_bool("is_exported"); - is_input=src.get_bool("is_input"); - is_output=src.get_bool("is_output"); - is_state_var=src.get_bool("is_state_var"); - is_parameter=src.get_bool("is_parameter"); - is_auxiliary=src.get_bool("is_auxiliary"); - is_weak=src.get_bool("is_weak"); - is_property=src.get_bool("property"); - is_lvalue=src.get_bool("lvalue"); - is_static_lifetime=src.get_bool("static_lifetime"); - is_thread_local=src.get_bool("thread_local"); - is_file_local=src.get_bool("file_local"); - is_extern=src.get_bool("is_extern"); - is_volatile=src.get_bool("is_volatile"); -} - void symbolt::swap(symbolt &b) { #define SYM_SWAP1(x) x.swap(b.x) diff --git a/src/util/symbol.h b/src/util/symbol.h index ca26306d6bf..078f80ad7b2 100644 --- a/src/util/symbol.h +++ b/src/util/symbol.h @@ -91,10 +91,6 @@ class symbolt void swap(symbolt &b); void show(std::ostream &out) const; - // serialization - irept to_irep() const; - void from_irep(const irept &src); - class symbol_exprt symbol_expr() const; bool is_shared() const From 5a22b5ef821e62e6ac816e3a27a945c7d6d63329 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Sat, 21 Apr 2018 11:05:16 +0100 Subject: [PATCH 55/93] Use existing irep_idts instead of strings --- src/cpp/cpp_typecheck_resolve.cpp | 4 ++-- src/goto-programs/remove_asm.cpp | 6 +++--- src/goto-symex/slice_by_trace.cpp | 2 +- src/solvers/smt2/smt2_parser.cpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cpp/cpp_typecheck_resolve.cpp b/src/cpp/cpp_typecheck_resolve.cpp index afc841da20b..647e1e14e46 100644 --- a/src/cpp/cpp_typecheck_resolve.cpp +++ b/src/cpp/cpp_typecheck_resolve.cpp @@ -839,11 +839,11 @@ exprt cpp_typecheck_resolvet::do_builtin( << ": " << original_scope->prefix << messaget::eom; } - else if(base_name=="size_t") + else if(base_name == ID_size_t) { dest=type_exprt(size_type()); } - else if(base_name=="ssize_t") + else if(base_name == ID_ssize_t) { dest=type_exprt(signed_size_type()); } diff --git a/src/goto-programs/remove_asm.cpp b/src/goto-programs/remove_asm.cpp index 0a514d04487..d93032a33aa 100644 --- a/src/goto-programs/remove_asm.cpp +++ b/src/goto-programs/remove_asm.cpp @@ -195,7 +195,7 @@ void remove_asmt::process_instruction( { gcc_asm_function_call("__asm_"+id2string(command), code, tmp_dest); } - else if(command=="sync") // Power + else if(command == ID_sync) // Power { goto_programt::targett t=tmp_dest.add_instruction(OTHER); t->source_location=code.source_location(); @@ -210,7 +210,7 @@ void remove_asmt::process_instruction( t->code.set(ID_RRcumul, true); t->code.set(ID_WRcumul, true); } - else if(command=="lwsync") // Power + else if(command == ID_lwsync) // Power { goto_programt::targett t=tmp_dest.add_instruction(OTHER); t->source_location=code.source_location(); @@ -223,7 +223,7 @@ void remove_asmt::process_instruction( t->code.set(ID_RWcumul, true); t->code.set(ID_RRcumul, true); } - else if(command=="isync") // Power + else if(command == ID_isync) // Power { goto_programt::targett t=tmp_dest.add_instruction(OTHER); t->source_location=code.source_location(); diff --git a/src/goto-symex/slice_by_trace.cpp b/src/goto-symex/slice_by_trace.cpp index 5218870e96f..9fe0036911d 100644 --- a/src/goto-symex/slice_by_trace.cpp +++ b/src/goto-symex/slice_by_trace.cpp @@ -244,7 +244,7 @@ void symex_slice_by_tracet::compute_ts_back( !i->io_args.empty() && i->io_args.front().id()=="trace_event") { - irep_idt event=i->io_args.front().get("event"); + irep_idt event = i->io_args.front().get(ID_event); if(!alphabet.empty()) { diff --git a/src/solvers/smt2/smt2_parser.cpp b/src/solvers/smt2/smt2_parser.cpp index 39bb7c0d519..d52bb8eafa1 100644 --- a/src/solvers/smt2/smt2_parser.cpp +++ b/src/solvers/smt2/smt2_parser.cpp @@ -774,7 +774,7 @@ exprt smt2_parsert::function_application() } else if(id=="rotate_left" || id=="rotate_right" || - id=="repeat" || + id == ID_repeat || id=="sign_extend" || id=="zero_extend") { @@ -826,7 +826,7 @@ exprt smt2_parsert::function_application() return typecast_exprt(op[0], unsigned_type); } - else if(id=="repeat") + else if(id == ID_repeat) { return nil_exprt(); } From edcd06fb8d3413f484594bf6252bd7dd43cadc5d Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Fri, 20 Apr 2018 23:08:40 +0100 Subject: [PATCH 56/93] Remove unused entries from the string table 21% of the entries do not occur in the code base (reduction from 844 to 663 entries). --- src/util/irep_ids.def | 181 ------------------------------------------ 1 file changed, 181 deletions(-) diff --git a/src/util/irep_ids.def b/src/util/irep_ids.def index 4f68f78051c..5714518c7fd 100644 --- a/src/util/irep_ids.def +++ b/src/util/irep_ids.def @@ -34,7 +34,6 @@ IREP_ID_ONE(dynamic_cast) IREP_ID_ONE(const_cast) IREP_ID_ONE(reinterpret_cast) IREP_ID_ONE(index) -IREP_ID_ONE(index_range) IREP_ID_ONE(ptrmember) IREP_ID_ONE(member) IREP_ID_ONE(member_name) @@ -47,7 +46,6 @@ IREP_ID_ONE(nand) IREP_ID_ONE(or) IREP_ID_ONE(nor) IREP_ID_ONE(xor) -IREP_ID_ONE(xnor) IREP_ID_ONE(not) IREP_ID_ONE(bitand) IREP_ID_ONE(bitor) @@ -61,7 +59,6 @@ IREP_ID_ONE(if) IREP_ID_ONE(symbol) IREP_ID_ONE(next_symbol) IREP_ID_ONE(nondet_symbol) -IREP_ID_ONE(predicate) IREP_ID_ONE(predicate_symbol) IREP_ID_ONE(predicate_next_symbol) IREP_ID_ONE(nondet_bool) @@ -148,13 +145,6 @@ IREP_ID_ONE(range) IREP_ID_ONE(from) IREP_ID_ONE(to) IREP_ID_ONE(module) -IREP_ID_ONE(module_instance) -IREP_ID_ONE(macromodule) -IREP_ID_ONE(primitive_module_instance) -IREP_ID_ONE(module_items) -IREP_ID_ONE(module_source) -IREP_ID_ONE(parameter_decl) -IREP_ID_ONE(local_parameter_decl) IREP_ID_ONE(parameter) IREP_ID_ONE(component_name) IREP_ID_ONE(component_number) @@ -170,13 +160,9 @@ IREP_ID_ONE(width) IREP_ID_ONE(components) IREP_ID_ONE(bv) IREP_ID_ONE(f) -IREP_ID_ONE(ports) -IREP_ID_ONE(port) -IREP_ID_ONE(offset) IREP_ID_ONE(with) IREP_ID_ONE(trans) IREP_ID_ONE(throw) -IREP_ID_ONE(catch) IREP_ID_ONE(try_catch) IREP_ID_ONE(noexcept) IREP_ID_ONE(CPROVER_throw) @@ -193,7 +179,6 @@ IREP_ID_ONE(constexpr) IREP_ID_ONE(inline) IREP_ID_ONE(forall) IREP_ID_ONE(exists) -IREP_ID_ONE(forever) IREP_ID_ONE(repeat) IREP_ID_ONE(extractbit) IREP_ID_ONE(extractbits) @@ -222,8 +207,6 @@ IREP_ID_ONE(java_string_literal) IREP_ID_ONE(printf) IREP_ID_ONE(input) IREP_ID_ONE(output) -IREP_ID_ONE(output_register) -IREP_ID_ONE(inout) IREP_ID_ONE(nondet) IREP_ID_ONE(NULL) IREP_ID_ONE(null) @@ -280,7 +263,6 @@ IREP_ID_ONE(ptr64) IREP_ID_ONE(char) IREP_ID_ONE(short) IREP_ID_ONE(long) -IREP_ID_ONE(longlong) IREP_ID_ONE(float) IREP_ID_ONE(double) IREP_ID_ONE(byte) @@ -299,9 +281,6 @@ IREP_ID_ONE(unsigned_long_long_int) IREP_ID_ONE(signed_int128) IREP_ID_ONE(unsigned_int128) IREP_ID_ONE(case) -IREP_ID_ONE(casex) -IREP_ID_ONE(casez) -IREP_ID_ONE(case_item) IREP_ID_TWO(C_inlined, #inlined) IREP_ID_TWO(C_hide, #hide) IREP_ID_ONE(hide) @@ -322,22 +301,6 @@ IREP_ID_ONE(bv_literals) IREP_ID_ONE(isfinite) IREP_ID_ONE(isinf) IREP_ID_ONE(isnormal) -IREP_ID_ONE(AG) -IREP_ID_ONE(AF) -IREP_ID_ONE(AX) -IREP_ID_ONE(EG) -IREP_ID_ONE(EF) -IREP_ID_ONE(EX) -IREP_ID_ONE(U) -IREP_ID_ONE(R) -IREP_ID_ONE(A) -IREP_ID_ONE(F) -IREP_ID_ONE(E) -IREP_ID_ONE(G) -IREP_ID_ONE(X) -IREP_ID_ONE(continuous_assign) -IREP_ID_ONE(blocking_assign) -IREP_ID_ONE(non_blocking_assign) IREP_ID_ONE(alignof) IREP_ID_ONE(clang_builtin_convertvector) IREP_ID_ONE(gcc_builtin_va_arg) @@ -353,11 +316,6 @@ IREP_ID_ONE(gcc_decimal128) IREP_ID_ONE(builtin_offsetof) IREP_ID_ONE(0) IREP_ID_ONE(1) -IREP_ID_ONE(8) -IREP_ID_ONE(16) -IREP_ID_ONE(32) -IREP_ID_ONE(64) -IREP_ID_ONE(128) IREP_ID_ONE(sizeof) IREP_ID_ONE(type_arg) IREP_ID_ONE(expr_arg) @@ -382,11 +340,9 @@ IREP_ID_TWO(mult, *) IREP_ID_TWO(div, /) IREP_ID_TWO(power, **) IREP_ID_ONE(factorial_power) -IREP_ID_ONE(component) IREP_ID_ONE(pretty_name) IREP_ID_TWO(C_class, #class) IREP_ID_TWO(C_interface, #interface) -IREP_ID_ONE(interface) IREP_ID_ONE(targets) IREP_ID_ONE(location) IREP_ID_ONE(labels) @@ -396,7 +352,6 @@ IREP_ID_ONE(designated_initializer) IREP_ID_ONE(designator) IREP_ID_ONE(member_designator) IREP_ID_ONE(index_designator) -IREP_ID_ONE(offset_designator) IREP_ID_TWO(C_constant, #constant) IREP_ID_TWO(C_volatile, #volatile) IREP_ID_TWO(C_restricted, #restricted) @@ -411,7 +366,6 @@ IREP_ID_ONE(byte_extract_little_endian) IREP_ID_ONE(byte_update_big_endian) IREP_ID_ONE(byte_update_little_endian) IREP_ID_ONE(replication) -IREP_ID_ONE(dummy) IREP_ID_ONE(init) IREP_ID_ONE(cprover_atomic) IREP_ID_ONE(atomic) @@ -424,18 +378,10 @@ IREP_ID_ONE(specc_notify) IREP_ID_ONE(specc_par) IREP_ID_ONE(specc_wait) IREP_ID_ONE(specc_event) -IREP_ID_ONE(bp_enforce) -IREP_ID_ONE(bp_abortif) -IREP_ID_ONE(bp_constrain) -IREP_ID_ONE(bp_schoose) -IREP_ID_ONE(bp_dead) -IREP_ID_ONE(instance) -IREP_ID_ONE(cover) IREP_ID_ONE(coverage_criterion) IREP_ID_ONE(initializer) IREP_ID_ONE(anonymous) IREP_ID_TWO(C_is_anonymous, #is_anonymous) -IREP_ID_ONE(is_macro) IREP_ID_ONE(is_enum_constant) IREP_ID_ONE(is_inline) IREP_ID_ONE(is_extern) @@ -475,34 +421,14 @@ IREP_ID_ONE(typename) IREP_ID_ONE(C) IREP_ID_ONE(cpp) IREP_ID_ONE(java) -IREP_ID_ONE(SpecC) -IREP_ID_ONE(SystemC) IREP_ID_ONE(decl_block) IREP_ID_ONE(decl_type) -IREP_ID_ONE(genvar) -IREP_ID_ONE(realtime) IREP_ID_ONE(parameters) -IREP_ID_ONE(parameter_assignments) -IREP_ID_ONE(named_parameter_assignment) -IREP_ID_ONE(specify) -IREP_ID_ONE(pullup) -IREP_ID_ONE(pulldown) -IREP_ID_ONE(automatic) -IREP_ID_ONE(rcmos) -IREP_ID_ONE(cmos) -IREP_ID_ONE(nmos) -IREP_ID_ONE(pmos) -IREP_ID_ONE(rnmos) -IREP_ID_ONE(rpmos) IREP_ID_ONE(wchar_t) IREP_ID_ONE(char16_t) IREP_ID_ONE(char32_t) IREP_ID_ONE(size_t) IREP_ID_ONE(ssize_t) -IREP_ID_ONE(inst) -IREP_ID_ONE(inst_builtin) -IREP_ID_ONE(always) -IREP_ID_ONE(initial) IREP_ID_ONE(mode) IREP_ID_ONE(this) IREP_ID_TWO(C_this, #this) @@ -514,7 +440,6 @@ IREP_ID_ONE(reduction_xor) IREP_ID_ONE(reduction_xnor) IREP_ID_TWO(C_zero_initializer, #zero_initializer) IREP_ID_ONE(body) -IREP_ID_ONE(entity) IREP_ID_ONE(temporary_object) IREP_ID_TWO(overflow_plus, overflow-+) IREP_ID_TWO(overflow_minus, overflow--) @@ -531,10 +456,7 @@ IREP_ID_ONE(static_object) IREP_ID_ONE(stack_object) IREP_ID_TWO(C_is_failed_symbol, #is_failed_symbol) IREP_ID_TWO(C_failed_symbol, #failed_symbol) -IREP_ID_ONE(list) -IREP_ID_ONE(map) IREP_ID_ONE(set) -IREP_ID_ONE(storage) IREP_ID_ONE(friend) IREP_ID_ONE(explicit) IREP_ID_ONE(storage_spec) @@ -548,21 +470,6 @@ IREP_ID_ONE(aligned) IREP_ID_TWO(C_alignment, #alignment) IREP_ID_ONE(vector) IREP_ID_ONE(abstract) -IREP_ID_ONE(bit) -IREP_ID_ONE(logic) -IREP_ID_ONE(chandle) -IREP_ID_ONE(reg) -IREP_ID_ONE(wire) -IREP_ID_ONE(tri) -IREP_ID_ONE(tri1) -IREP_ID_ONE(supply0) -IREP_ID_ONE(wand) -IREP_ID_ONE(triand) -IREP_ID_ONE(tri0) -IREP_ID_ONE(supply1) -IREP_ID_ONE(wor) -IREP_ID_ONE(trior) -IREP_ID_ONE(trireg) IREP_ID_ONE(function_application) IREP_ID_ONE(cpp_declarator) IREP_ID_ONE(cpp_linkage_spec) @@ -576,57 +483,12 @@ IREP_ID_TWO(C_c_type, #c_type) IREP_ID_ONE(namespace) IREP_ID_ONE(linkage) IREP_ID_ONE(decltype) -IREP_ID_ONE(buf) -IREP_ID_ONE(bufif0) -IREP_ID_ONE(bufif1) -IREP_ID_ONE(notif0) -IREP_ID_ONE(notif1) -IREP_ID_ONE(task) -IREP_ID_TWO(C_little_endian, #little_endian) -IREP_ID_TWO(C_offset, #offset) IREP_ID_TWO(C_tag_only_declaration, #tag_only_declaration) IREP_ID_ONE(struct_tag) IREP_ID_ONE(union_tag) IREP_ID_ONE(c_enum_tag) -IREP_ID_ONE(enum_constant) -IREP_ID_ONE(bit_select) -IREP_ID_ONE(part_select) -IREP_ID_ONE(indexed_part_select_plus) -IREP_ID_ONE(indexed_part_select_minus) -IREP_ID_ONE(generate_block) -IREP_ID_ONE(generate_assign) -IREP_ID_ONE(generate_skip) -IREP_ID_ONE(generate_case) -IREP_ID_ONE(generate_if) -IREP_ID_ONE(generate_for) -IREP_ID_ONE(delay) -IREP_ID_ONE(verilog_cycle_delay) -IREP_ID_ONE(sva_cycle_delay) -IREP_ID_ONE(sva_sequence_throughout) -IREP_ID_ONE(sva_sequence_concatenation) -IREP_ID_ONE(sva_sequence_first_match) -IREP_ID_ONE(sva_always) -IREP_ID_ONE(sva_nexttime) -IREP_ID_ONE(sva_s_nexttime) -IREP_ID_ONE(sva_eventually) -IREP_ID_ONE(sva_s_eventually) -IREP_ID_ONE(sva_until) -IREP_ID_ONE(sva_s_until) -IREP_ID_ONE(sva_until_with) -IREP_ID_ONE(sva_s_until_with) -IREP_ID_ONE(sva_overlapped_implication) -IREP_ID_ONE(sva_non_overlapped_implication) -IREP_ID_ONE(hierarchical_identifier) -IREP_ID_ONE(named_port_connection) -IREP_ID_ONE(named_block) -IREP_ID_ONE(verilog_primitive_module) -IREP_ID_ONE(verilog_module) IREP_ID_ONE(verilog_case_equality) IREP_ID_ONE(verilog_case_inequality) -IREP_ID_ONE(event_guard) -IREP_ID_ONE(posedge) -IREP_ID_ONE(negedge) -IREP_ID_ONE(pointer_and_address_pair) IREP_ID_ONE(user_specified_predicate) IREP_ID_ONE(user_specified_parameter_predicates) IREP_ID_ONE(user_specified_return_predicates) @@ -644,13 +506,9 @@ IREP_ID_ONE(msc_if_not_exists) IREP_ID_ONE(msc_underlying_type) IREP_ID_ONE(msc_based) IREP_ID_ONE(alias) -IREP_ID_ONE(auto_object) -IREP_ID_ONE(ssa_object) IREP_ID_ONE(ptr_object) IREP_ID_TWO(C_c_sizeof_type, #c_sizeof_type) IREP_ID_ONE(array_update) -IREP_ID_ONE(struct_update) -IREP_ID_ONE(union_update) IREP_ID_ONE(update) IREP_ID_ONE(float_debug1) IREP_ID_ONE(float_debug2) @@ -659,10 +517,7 @@ IREP_ID_ONE(gcc_attribute_mode) IREP_ID_TWO(built_in, ) IREP_ID_ONE(exception_list) IREP_ID_ONE(exception_id) -IREP_ID_ONE(priority) IREP_ID_ONE(predicate_passive_symbol) -IREP_ID_ONE(all) -IREP_ID_ONE(when) IREP_ID_ONE(cw_va_arg_typeof) IREP_ID_ONE(fence) IREP_ID_ONE(sync) @@ -676,7 +531,6 @@ IREP_ID_ONE(RRcumul) IREP_ID_ONE(RWcumul) IREP_ID_ONE(WWcumul) IREP_ID_ONE(WRcumul) -IREP_ID_ONE(claim) IREP_ID_ONE(generic_selection) IREP_ID_ONE(generic_associations) IREP_ID_ONE(generic_association) @@ -685,13 +539,7 @@ IREP_ID_ONE(floatbv_minus) IREP_ID_ONE(floatbv_mult) IREP_ID_ONE(floatbv_div) IREP_ID_ONE(floatbv_rem) -IREP_ID_ONE(floatbv_sin) -IREP_ID_ONE(floatbv_cos) IREP_ID_ONE(floatbv_typecast) -IREP_ID_ONE(read) -IREP_ID_ONE(write) -IREP_ID_ONE(native) -IREP_ID_ONE(final) IREP_ID_ONE(compound_literal) IREP_ID_ONE(custom_bv) IREP_ID_ONE(custom_unsignedbv) @@ -699,7 +547,6 @@ IREP_ID_ONE(custom_signedbv) IREP_ID_ONE(custom_fixedbv) IREP_ID_ONE(custom_floatbv) IREP_ID_TWO(C_SSA_symbol, #SSA_symbol) -IREP_ID_TWO(C_full_identifier, #full_identifier) IREP_ID_ONE(L0) IREP_ID_ONE(L1) IREP_ID_ONE(L2) @@ -707,26 +554,12 @@ IREP_ID_ONE(L1_object_identifier) IREP_ID_ONE(already_typechecked) IREP_ID_TWO(C_va_arg_type, #va_arg_type) IREP_ID_ONE(smt2_symbol) -IREP_ID_ONE(VHDL) -IREP_ID_ONE(Verilog) -IREP_ID_ONE(verilog_realtime) IREP_ID_ONE(onehot) IREP_ID_ONE(onehot0) -IREP_ID_ONE(verilog_star_event) -IREP_ID_ONE(verilog_attribute) -IREP_ID_ONE(time) -IREP_ID_ONE(fork) -IREP_ID_ONE(disable) -IREP_ID_ONE(wait) -IREP_ID_ONE(deassign) -IREP_ID_ONE(force) -IREP_ID_ONE(release) IREP_ID_ONE(popcount) IREP_ID_ONE(function_type) IREP_ID_ONE(noreturn) IREP_ID_TWO(C_noreturn, #noreturn) -IREP_ID_ONE(process) -IREP_ID_ONE(signal) IREP_ID_ONE(weak) IREP_ID_ONE(is_weak) IREP_ID_TWO(C_spec_loop_invariant, #spec_loop_invariant) @@ -736,13 +569,6 @@ IREP_ID_ONE(virtual_function) IREP_ID_TWO(C_element_type, #element_type) IREP_ID_ONE(working_directory) IREP_ID_ONE(section) -IREP_ID_ONE(msb) -IREP_ID_ONE(lsb) -IREP_ID_ONE(verilog_signed_vector) -IREP_ID_ONE(verilog_unsigned_vector) -IREP_ID_ONE(verilog_array) -IREP_ID_ONE(low) -IREP_ID_ONE(high) IREP_ID_ONE(bswap) IREP_ID_ONE(java_bytecode_index) IREP_ID_ONE(java_instanceof) @@ -758,7 +584,6 @@ IREP_ID_ONE(cprover_associate_array_to_pointer_func) IREP_ID_ONE(cprover_associate_length_to_array_func) IREP_ID_ONE(cprover_char_literal_func) IREP_ID_ONE(cprover_string_literal_func) -IREP_ID_ONE(cprover_string_array_of_char_pointer_func) IREP_ID_ONE(cprover_string_char_at_func) IREP_ID_ONE(cprover_string_char_set_func) IREP_ID_ONE(cprover_string_code_point_at_func) @@ -794,13 +619,11 @@ IREP_ID_ONE(cprover_string_insert_bool_func) IREP_ID_ONE(cprover_string_insert_char_func) IREP_ID_ONE(cprover_string_insert_float_func) IREP_ID_ONE(cprover_string_insert_double_func) -IREP_ID_ONE(cprover_string_insert_char_array_func) IREP_ID_ONE(cprover_string_is_prefix_func) IREP_ID_ONE(cprover_string_is_suffix_func) IREP_ID_ONE(cprover_string_is_empty_func) IREP_ID_ONE(cprover_string_last_index_of_func) IREP_ID_ONE(cprover_string_length_func) -IREP_ID_ONE(cprover_string_data_func) IREP_ID_ONE(cprover_string_of_int_func) IREP_ID_ONE(cprover_string_of_int_hex_func) IREP_ID_ONE(cprover_string_of_long_func) @@ -809,17 +632,14 @@ IREP_ID_ONE(cprover_string_of_float_func) IREP_ID_ONE(cprover_string_of_float_scientific_notation_func) IREP_ID_ONE(cprover_string_of_double_func) IREP_ID_ONE(cprover_string_of_char_func) -IREP_ID_ONE(cprover_string_of_char_array_func) IREP_ID_ONE(cprover_string_parse_int_func) IREP_ID_ONE(cprover_string_replace_func) IREP_ID_ONE(cprover_string_set_length_func) IREP_ID_ONE(cprover_string_startswith_func) IREP_ID_ONE(cprover_string_substring_func) -IREP_ID_ONE(cprover_string_to_char_array_func) IREP_ID_ONE(cprover_string_to_lower_case_func) IREP_ID_ONE(cprover_string_to_upper_case_func) IREP_ID_ONE(cprover_string_trim_func) -IREP_ID_ONE(cprover_string_value_of_func) IREP_ID_ONE(skip_initialize) IREP_ID_ONE(basic_block_covered_lines) IREP_ID_ONE(is_nondet_nullable) @@ -831,7 +651,6 @@ IREP_ID_ONE(integer_dereference) IREP_ID_TWO(C_java_generic_parameter, #java_generic_parameter) IREP_ID_TWO(C_java_generic_type, #java_generic_type) IREP_ID_TWO(C_java_generics_class_type, #java_generics_class_type) -IREP_ID_TWO(C_specialized_generic_java_class, #specialized_generic_java_class) IREP_ID_TWO(C_java_implicitly_generic_class_type, #java_implicitly_generic_class_type) IREP_ID_TWO(C_java_generic_symbol, #java_generic_symbol) IREP_ID_TWO(generic_types, #generic_types) From 9103fb7ef15fd8f95186fe27d98e174484c14e68 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Sat, 21 Apr 2018 11:59:37 +0100 Subject: [PATCH 57/93] Check that the string table does not include unused entries --- .travis.yml | 7 +++++++ scripts/string_table_check.sh | 30 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100755 scripts/string_table_check.sh diff --git a/.travis.yml b/.travis.yml index 52d548e3de2..6987a0b55d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,6 +38,13 @@ jobs: script: scripts/travis_lint.sh before_cache: + - &string-table-check + stage: Linter + Doxygen + non-debug Ubuntu/gcc-5 test + env: NAME="string-table" + install: + script: scripts/string_table_check.sh + before_cache: + - stage: Linter + Doxygen + non-debug Ubuntu/gcc-5 test env: NAME="DOXYGEN-CHECK" addons: diff --git a/scripts/string_table_check.sh b/scripts/string_table_check.sh new file mode 100755 index 00000000000..5bf6d4b2dd2 --- /dev/null +++ b/scripts/string_table_check.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +whitelist=" \ +" + +cleanup() +{ + rm -f "$ids_file" +} + +ids_file=$(mktemp) + +trap cleanup EXIT + +gcc -E -P -x c src/util/irep_ids.def \ + -D'IREP_ID_ONE(x)=ID_ ## x' -D'IREP_ID_TWO(x,y)=ID_ ## x' > $ids_file + +for w in $whitelist +do + perl -p -i -e "s/^$w\n//" $ids_file +done + +for i in $(<$ids_file) +do + if ! git grep -w -q -c -F $i + then + echo "$i is never used" + exit 1 + fi +done From e962aec9c26a19082038cb9ae4d48b351050ab1e Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Wed, 25 Apr 2018 15:06:51 +0100 Subject: [PATCH 58/93] Fix Doxygen syntax --- src/util/irep_ids.def | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/util/irep_ids.def b/src/util/irep_ids.def index 5714518c7fd..4bc64e911e3 100644 --- a/src/util/irep_ids.def +++ b/src/util/irep_ids.def @@ -1,4 +1,5 @@ -/// \file List of irep id names and values. +/// \file +/// List of irep id names and values. /// For an explanation of how this works, see irep_ids.h. IREP_ID_TWO(empty_string, ) From bb06869e41c5927cb78223443c3aad9bab78ddf7 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Wed, 25 Apr 2018 09:22:21 +0100 Subject: [PATCH 59/93] Move enum idt to the single translation unit that actually requires it --- src/util/irep_ids.cpp | 8 ++++++++ src/util/irep_ids.h | 10 +--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/util/irep_ids.cpp b/src/util/irep_ids.cpp index 5151cd92fed..5a6bc4e525d 100644 --- a/src/util/irep_ids.cpp +++ b/src/util/irep_ids.cpp @@ -27,6 +27,14 @@ const char *irep_ids_table[]= #ifdef USE_DSTRING +enum class idt:unsigned +{ +#define IREP_ID_ONE(the_id) id_##the_id, +#define IREP_ID_TWO(the_id, str) id_##the_id, + +#include "irep_ids.def" // NOLINT(build/include) +}; + #define IREP_ID_ONE(the_id) \ const dstringt ID_##the_id=dstringt::make_from_table_index( \ static_cast(idt::id_##the_id)); diff --git a/src/util/irep_ids.h b/src/util/irep_ids.h index 2fec6ff4114..7d946bed305 100644 --- a/src/util/irep_ids.h +++ b/src/util/irep_ids.h @@ -33,14 +33,6 @@ Author: Reuben Thomas, reuben.thomas@me.com /// into a const extern irep_idt with the variable name `ID_param` and the /// string value `"contents"`. -enum class idt:unsigned -{ -#define IREP_ID_ONE(the_id) id_##the_id, -#define IREP_ID_TWO(the_id, str) id_##the_id, - -#include "irep_ids.def" -}; - #ifdef USE_DSTRING #define IREP_ID_ONE(the_id) extern const dstringt ID_##the_id; @@ -53,6 +45,6 @@ enum class idt:unsigned #endif -#include "irep_ids.def" // NOLINT(build/include) +#include "irep_ids.def" #endif From 9f5a216c1e0aecc2eabc591070b3fff7a7189b33 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Wed, 25 Apr 2018 09:42:13 +0100 Subject: [PATCH 60/93] Added an extension point for irep ids --- src/util/irep_ids.def | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/util/irep_ids.def b/src/util/irep_ids.def index 4bc64e911e3..78ff9b00e16 100644 --- a/src/util/irep_ids.def +++ b/src/util/irep_ids.def @@ -666,5 +666,13 @@ IREP_ID_TWO(overlay_class, java::com.diffblue.OverlayClassImplementation) IREP_ID_TWO(overlay_method, java::com.diffblue.OverlayMethodImplementation) IREP_ID_ONE(annotations) +// Projects depending on this code base that wish to extend the list of +// available ids should provide a file local_irep_ids.h in their source tree and +// add -D'LOCAL_IREP_IDS=' to their compiler command +// line. +#ifdef LOCAL_IREP_IDS +#include LOCAL_IREP_IDS +#endif + #undef IREP_ID_ONE #undef IREP_ID_TWO From 569b1e700354f1a20169aed1897c1c43d23f4aea Mon Sep 17 00:00:00 2001 From: "Lukasz A.J. Wrona" Date: Wed, 25 Apr 2018 16:06:12 +0100 Subject: [PATCH 61/93] Rephrase and justify curly brace alignment exceptions --- CODING_STANDARD.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CODING_STANDARD.md b/CODING_STANDARD.md index 6fbe519b293..c218cdf859b 100644 --- a/CODING_STANDARD.md +++ b/CODING_STANDARD.md @@ -19,9 +19,10 @@ Formatting is enforced using clang-format. For more information about this, see - Nested function calls do not need to be broken up into separate lines even if the outer function call does. - If a method is bigger than 50 lines, break it into parts. -- Put matching `{ }` into the same column, except for lambdas, where you should - place `{` directly after the closing `)`. This rule also doesn't apply to - initializer lists. +- Put matching `{ }` into the same column, except for initializer lists and + lambdas, where you should place `{` directly after the closing `)`. This is + to comply with clang-format, which doesn't support aligned curly braces in + these cases. - Spaces around binary operators (`=`, `+`, `==` ...) - Space after comma (parameter lists, argument lists, ...) - Space after colon inside `for` From 52839f84034f6a32021c276e7528aa02056b013a Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Wed, 25 Apr 2018 14:31:36 +0000 Subject: [PATCH 62/93] array_size symbols: set mode and avoid redundant settings The symbolt constructor already takes care of initialising fields to false. --- src/ansi-c/c_typecheck_type.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ansi-c/c_typecheck_type.cpp b/src/ansi-c/c_typecheck_type.cpp index 0a4d12ba913..1acc58d2f20 100644 --- a/src/ansi-c/c_typecheck_type.cpp +++ b/src/ansi-c/c_typecheck_type.cpp @@ -581,10 +581,9 @@ void c_typecheck_baset::typecheck_array_type(array_typet &type) new_symbol.base_name=id2string(current_symbol.base_name)+suffix; new_symbol.type=size.type(); new_symbol.type.set(ID_C_constant, true); - new_symbol.is_type=false; - new_symbol.is_static_lifetime=false; new_symbol.value=size; new_symbol.location=source_location; + new_symbol.mode = mode; symbol_table.add(new_symbol); From c356e4517c610b04c7fdcd36a6f5382d7b34a428 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Wed, 25 Apr 2018 14:34:44 +0000 Subject: [PATCH 63/93] symex_dynamic::dynamic_object_size* are constants We do not have a notion of guaranteed constants, thus mark them thread-local via the auxiliary_symbolt constructor. This avoids repeated renaming of the size of an array, which resulted in spurious errors in concurrent programs (e.g., in SV-COMP running "cbmc --unwind 2 --stop-on-fail --32 c/pthread-C-DAC/pthread-numerical-integration_true-unreach-call.i"). --- regression/cbmc-concurrency/malloc2/main.c | 21 +++++++++++++++++++ regression/cbmc-concurrency/malloc2/test.desc | 8 +++++++ src/goto-symex/symex_builtin_functions.cpp | 5 +++-- 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 regression/cbmc-concurrency/malloc2/main.c create mode 100644 regression/cbmc-concurrency/malloc2/test.desc diff --git a/regression/cbmc-concurrency/malloc2/main.c b/regression/cbmc-concurrency/malloc2/main.c new file mode 100644 index 00000000000..8634e886ccf --- /dev/null +++ b/regression/cbmc-concurrency/malloc2/main.c @@ -0,0 +1,21 @@ +#include +#include + +_Bool set_done; +int *ptr; + +void *set_x(void *arg) +{ + *(int *)arg = 10; + set_done = 1; +} + +int main(int argc, char *argv[]) +{ + __CPROVER_assume(argc >= sizeof(int)); + ptr = malloc(argc); + __CPROVER_ASYNC_1: set_x(ptr); + __CPROVER_assume(set_done); + assert(*ptr == 10); + return 0; +} diff --git a/regression/cbmc-concurrency/malloc2/test.desc b/regression/cbmc-concurrency/malloc2/test.desc new file mode 100644 index 00000000000..9efefbc7362 --- /dev/null +++ b/regression/cbmc-concurrency/malloc2/test.desc @@ -0,0 +1,8 @@ +CORE +main.c + +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/src/goto-symex/symex_builtin_functions.cpp b/src/goto-symex/symex_builtin_functions.cpp index 1a7ba984e82..6294e47b3a1 100644 --- a/src/goto-symex/symex_builtin_functions.cpp +++ b/src/goto-symex/symex_builtin_functions.cpp @@ -138,14 +138,15 @@ void goto_symext::symex_allocate( { exprt &size=to_array_type(object_type).size(); - symbolt size_symbol; + auxiliary_symbolt size_symbol; size_symbol.base_name= "dynamic_object_size"+std::to_string(dynamic_counter); size_symbol.name="symex_dynamic::"+id2string(size_symbol.base_name); - size_symbol.is_lvalue=true; size_symbol.type=tmp_size.type(); size_symbol.mode = mode; + size_symbol.type.set(ID_C_constant, true); + size_symbol.value = size; state.symbol_table.add(size_symbol); From 4e623e975083ec8f6fb90fc706c154df574002e5 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 21 Apr 2018 22:31:13 +0100 Subject: [PATCH 64/93] Utility functions to get mode and language --- src/langapi/language_util.cpp | 28 +++---------------- src/langapi/mode.cpp | 51 ++++++++++++++++++++++++++++++----- src/langapi/mode.h | 5 ++++ 3 files changed, 54 insertions(+), 30 deletions(-) diff --git a/src/langapi/language_util.cpp b/src/langapi/language_util.cpp index 7a2e691af38..87c51c9877f 100644 --- a/src/langapi/language_util.cpp +++ b/src/langapi/language_util.cpp @@ -17,32 +17,12 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include "language.h" #include "mode.h" -static std::unique_ptr get_language( - const namespacet &ns, - const irep_idt &identifier) -{ - const symbolt *symbol; - - if(identifier=="" || - ns.lookup(identifier, symbol) || - symbol->mode=="") - return get_default_language(); - - std::unique_ptr ptr=get_language_from_mode(symbol->mode); - - if(ptr==nullptr) - throw "symbol `"+id2string(symbol->name)+ - "' has unknown mode '"+id2string(symbol->mode)+"'"; - - return ptr; -} - std::string from_expr( const namespacet &ns, const irep_idt &identifier, const exprt &expr) { - std::unique_ptr p(get_language(ns, identifier)); + std::unique_ptr p(get_language_from_identifier(ns, identifier)); std::string result; p->from_expr(expr, result, ns); @@ -55,7 +35,7 @@ std::string from_type( const irep_idt &identifier, const typet &type) { - std::unique_ptr p(get_language(ns, identifier)); + std::unique_ptr p(get_language_from_identifier(ns, identifier)); std::string result; p->from_type(type, result, ns); @@ -68,7 +48,7 @@ std::string type_to_name( const irep_idt &identifier, const typet &type) { - std::unique_ptr p(get_language(ns, identifier)); + std::unique_ptr p(get_language_from_identifier(ns, identifier)); std::string result; p->type_to_name(type, result, ns); @@ -93,7 +73,7 @@ exprt to_expr( const irep_idt &identifier, const std::string &src) { - std::unique_ptr p(get_language(ns, identifier)); + std::unique_ptr p(get_language_from_identifier(ns, identifier)); null_message_handlert null_message_handler; p->set_message_handler(null_message_handler); diff --git a/src/langapi/mode.cpp b/src/langapi/mode.cpp index dd12882c544..546f866d23c 100644 --- a/src/langapi/mode.cpp +++ b/src/langapi/mode.cpp @@ -18,6 +18,9 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include "language.h" +#include +#include + struct language_entryt { language_factoryt factory; @@ -39,15 +42,51 @@ void register_language(language_factoryt factory) std::unique_ptr get_language_from_mode(const irep_idt &mode) { - for(languagest::const_iterator it=languages.begin(); - it!=languages.end(); - it++) - if(mode==it->mode) - return it->factory(); + for(const auto &language : languages) + if(mode == language.mode) + return language.factory(); return nullptr; } +/// Get the mode of the given identifier's symbol +/// \param ns: a namespace +/// \param identifier: an identifier +/// \return the mode, e.g. `ID_C`, if the identifier is in the given +/// symbol table, or `ID_unknown` otherwise +const irep_idt & +get_mode_from_identifier(const namespacet &ns, const irep_idt &identifier) +{ + if(identifier.empty()) + return ID_unknown; + const symbolt *symbol; + if(ns.lookup(identifier, symbol)) + return ID_unknown; + return symbol->mode; +} + +/// Get the language corresponding to the mode of the given identifier's symbol +/// \param ns: a namespace +/// \param identifier: an identifier +/// \return the corresponding language if the mode is not `ID_unknown`, or +/// the default language otherwise; +/// Note: It is assumed as an invariant that languages of symbols in the symbol +/// table have been registered. +std::unique_ptr +get_language_from_identifier(const namespacet &ns, const irep_idt &identifier) +{ + const irep_idt &mode = get_mode_from_identifier(ns, identifier); + if(mode == ID_unknown) + return get_default_language(); + + std::unique_ptr language = get_language_from_mode(mode); + INVARIANT( + language, + "symbol `" + id2string(identifier) + "' has unknown mode '" + + id2string(mode) + "'"); + return language; +} + std::unique_ptr get_language_from_filename( const std::string &filename) { @@ -85,6 +124,6 @@ std::unique_ptr get_language_from_filename( std::unique_ptr get_default_language() { - assert(!languages.empty()); + PRECONDITION(!languages.empty()); return languages.front().factory(); } diff --git a/src/langapi/mode.h b/src/langapi/mode.h index 3edb7a30be8..3223cf4a960 100644 --- a/src/langapi/mode.h +++ b/src/langapi/mode.h @@ -15,8 +15,13 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include // unique_ptr class languaget; +class namespacet; std::unique_ptr get_language_from_mode(const irep_idt &mode); +const irep_idt & +get_mode_from_identifier(const namespacet &ns, const irep_idt &identifier); +std::unique_ptr +get_language_from_identifier(const namespacet &ns, const irep_idt &identifier); std::unique_ptr get_language_from_filename( const std::string &filename); std::unique_ptr get_default_language(); From c44aa9dee4f7337834d0f35a6c41f7f1321d2afd Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sun, 22 Apr 2018 14:14:03 +0100 Subject: [PATCH 65/93] Add more doxygen to language.h and mode.h --- src/langapi/language.h | 21 +++++++++++++++++++++ src/langapi/mode.cpp | 13 +++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/langapi/language.h b/src/langapi/language.h index a3b6cbc0206..9e35daa17c9 100644 --- a/src/langapi/language.h +++ b/src/langapi/language.h @@ -114,21 +114,42 @@ class languaget:public messaget // conversion of expressions + /// Formats the given expression in a language-specific way + /// \param expr: the expression to format + /// \param code: the formatted expression + /// \param ns: a namespace + /// \return false if conversion succeeds virtual bool from_expr( const exprt &expr, std::string &code, const namespacet &ns); + /// Formats the given type in a language-specific way + /// \param type: the type to format + /// \param code: the formatted type + /// \param ns: a namespace + /// \return false if conversion succeeds virtual bool from_type( const typet &type, std::string &code, const namespacet &ns); + /// Encodes the given type in a language-specific way + /// \param type: the type to encode + /// \param name: the encoded type + /// \param ns: a namespace + /// \return false if the conversion succeeds virtual bool type_to_name( const typet &type, std::string &name, const namespacet &ns); + /// Parses the given string into an expression + /// \param code: the string to parse + /// \param module: prefix to be used for identifiers + /// \param expr: the parsed expression + /// \param ns: a namespace + /// \return false if the conversion succeeds virtual bool to_expr( const std::string &code, const std::string &module, diff --git a/src/langapi/mode.cpp b/src/langapi/mode.cpp index 546f866d23c..d2bc2474189 100644 --- a/src/langapi/mode.cpp +++ b/src/langapi/mode.cpp @@ -31,6 +31,10 @@ struct language_entryt typedef std::list languagest; languagest languages; +/// Register a language +/// Note: registering a language is required for using the functions +/// in language_util.h +/// \param factory: a language factory, e.g. `new_ansi_c_language` void register_language(language_factoryt factory) { languages.push_back(language_entryt()); @@ -40,6 +44,9 @@ void register_language(language_factoryt factory) languages.back().mode=l->id(); } +/// Get the language corresponding to the given mode +/// \param mode: the mode, e.g. `ID_C` +/// \return the language or `nullptr` if the language has not been registered std::unique_ptr get_language_from_mode(const irep_idt &mode) { for(const auto &language : languages) @@ -87,6 +94,10 @@ get_language_from_identifier(const namespacet &ns, const irep_idt &identifier) return language; } +/// Get the language corresponding to the registered file name extensions +/// \param filename: a filename +/// \return the corresponding language or `nullptr` if the extension cannot +/// be resolved to any registered language std::unique_ptr get_language_from_filename( const std::string &filename) { @@ -122,6 +133,8 @@ std::unique_ptr get_language_from_filename( return nullptr; } +/// Returns the default language +/// \return the first registered language std::unique_ptr get_default_language() { PRECONDITION(!languages.empty()); From b57be97975195be77c7320cddee4e0eaf39cd2d5 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Wed, 25 Apr 2018 22:43:56 +0100 Subject: [PATCH 66/93] Add Makefile dependency for smt2_solver --- src/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Makefile b/src/Makefile index d570dbb641a..d28a2bdc976 100644 --- a/src/Makefile +++ b/src/Makefile @@ -25,6 +25,8 @@ languages: util.dir langapi.dir \ cpp.dir ansi-c.dir xmllang.dir assembler.dir java_bytecode.dir \ jsil.dir +solvers.dir: util.dir langapi.dir + goto-instrument.dir: languages goto-programs.dir pointer-analysis.dir \ goto-symex.dir linking.dir analyses.dir solvers.dir \ json.dir From df9f19a95e3f95364c26bd3a2f3e0d745d3b3a95 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Wed, 25 Apr 2018 22:24:52 +0100 Subject: [PATCH 67/93] Factor out java new removal into separate pass --- src/goto-programs/builtin_functions.cpp | 210 ------------ src/goto-programs/goto_convert.cpp | 48 ++- src/java_bytecode/Makefile | 3 +- src/java_bytecode/remove_java_new.cpp | 438 ++++++++++++++++++++++++ src/java_bytecode/remove_java_new.h | 40 +++ 5 files changed, 511 insertions(+), 228 deletions(-) create mode 100644 src/java_bytecode/remove_java_new.cpp create mode 100644 src/java_bytecode/remove_java_new.h diff --git a/src/goto-programs/builtin_functions.cpp b/src/goto-programs/builtin_functions.cpp index 666c463bee9..ba1dfb7c685 100644 --- a/src/goto-programs/builtin_functions.cpp +++ b/src/goto-programs/builtin_functions.cpp @@ -539,216 +539,6 @@ void goto_convertt::do_cpp_new( dest.destructive_append(tmp_initializer); } -void goto_convertt::do_java_new( - const exprt &lhs, - const side_effect_exprt &rhs, - goto_programt &dest) -{ - PRECONDITION(!lhs.is_nil()); - PRECONDITION(rhs.operands().empty()); - PRECONDITION(rhs.type().id() == ID_pointer); - source_locationt location=rhs.source_location(); - typet object_type=rhs.type().subtype(); - - // build size expression - exprt object_size=size_of_expr(object_type, ns); - CHECK_RETURN(object_size.is_not_nil()); - - // we produce a malloc side-effect, which stays - side_effect_exprt malloc_expr(ID_allocate, rhs.type()); - malloc_expr.copy_to_operands(object_size); - // could use true and get rid of the code below - malloc_expr.copy_to_operands(false_exprt()); - - goto_programt::targett t_n=dest.add_instruction(ASSIGN); - t_n->code=code_assignt(lhs, malloc_expr); - t_n->source_location=location; - - // zero-initialize the object - dereference_exprt deref(lhs, object_type); - exprt zero_object= - zero_initializer(object_type, location, ns, get_message_handler()); - set_class_identifier( - to_struct_expr(zero_object), ns, to_symbol_type(object_type)); - goto_programt::targett t_i=dest.add_instruction(ASSIGN); - t_i->code=code_assignt(deref, zero_object); - t_i->source_location=location; -} - -void goto_convertt::do_java_new_array( - const exprt &lhs, - const side_effect_exprt &rhs, - goto_programt &dest) -{ - PRECONDITION(!lhs.is_nil()); // do_java_new_array without lhs not implemented - PRECONDITION(rhs.operands().size() >= 1); // one per dimension - PRECONDITION(rhs.type().id() == ID_pointer); - - source_locationt location=rhs.source_location(); - typet object_type=rhs.type().subtype(); - PRECONDITION(ns.follow(object_type).id() == ID_struct); - - // build size expression - exprt object_size=size_of_expr(object_type, ns); - - CHECK_RETURN(!object_size.is_nil()); - - // we produce a malloc side-effect, which stays - side_effect_exprt malloc_expr(ID_allocate, rhs.type()); - malloc_expr.copy_to_operands(object_size); - // code use true and get rid of the code below - malloc_expr.copy_to_operands(false_exprt()); - - goto_programt::targett t_n=dest.add_instruction(ASSIGN); - t_n->code=code_assignt(lhs, malloc_expr); - t_n->source_location=location; - - const struct_typet &struct_type=to_struct_type(ns.follow(object_type)); - - // Ideally we would have a check for `is_valid_java_array(struct_type)` but - // `is_valid_java_array is part of the java_bytecode module and we cannot - // introduce such dependencies. We do this simple check instead: - PRECONDITION(struct_type.components().size()==3); - - // Init base class: - dereference_exprt deref(lhs, object_type); - exprt zero_object= - zero_initializer(object_type, location, ns, get_message_handler()); - set_class_identifier( - to_struct_expr(zero_object), ns, to_symbol_type(object_type)); - goto_programt::targett t_i=dest.add_instruction(ASSIGN); - t_i->code=code_assignt(deref, zero_object); - t_i->source_location=location; - - // if it's an array, we need to set the length field - member_exprt length( - deref, - struct_type.components()[1].get_name(), - struct_type.components()[1].type()); - goto_programt::targett t_s=dest.add_instruction(ASSIGN); - t_s->code=code_assignt(length, rhs.op0()); - t_s->source_location=location; - - // we also need to allocate space for the data - member_exprt data( - deref, - struct_type.components()[2].get_name(), - struct_type.components()[2].type()); - - // Allocate a (struct realtype**) instead of a (void**) if possible. - const irept &given_element_type=object_type.find(ID_C_element_type); - typet allocate_data_type; - if(given_element_type.is_not_nil()) - { - allocate_data_type= - pointer_type(static_cast(given_element_type)); - } - else - allocate_data_type=data.type(); - - side_effect_exprt data_java_new_expr( - ID_java_new_array_data, allocate_data_type); - - // The instruction may specify a (hopefully small) upper bound on the - // array size, in which case we allocate a fixed-length array that may - // be larger than the `length` member rather than use a true variable- - // length array, which produces a more complex formula in the current - // backend. - const irept size_bound=rhs.find(ID_length_upper_bound); - if(size_bound.is_nil()) - data_java_new_expr.set(ID_size, rhs.op0()); - else - data_java_new_expr.set(ID_size, size_bound); - - // Must directly assign the new array to a temporary - // because goto-symex will notice `x=side_effect_exprt` but not - // `x=typecast_exprt(side_effect_exprt(...))` - symbol_exprt new_array_data_symbol = - new_tmp_symbol( - data_java_new_expr.type(), "new_array_data", dest, location, ID_java) - .symbol_expr(); - goto_programt::targett t_p2=dest.add_instruction(ASSIGN); - t_p2->code=code_assignt(new_array_data_symbol, data_java_new_expr); - t_p2->source_location=location; - - goto_programt::targett t_p=dest.add_instruction(ASSIGN); - exprt cast_java_new=new_array_data_symbol; - if(cast_java_new.type()!=data.type()) - cast_java_new=typecast_exprt(cast_java_new, data.type()); - t_p->code=code_assignt(data, cast_java_new); - t_p->source_location=location; - - // zero-initialize the data - if(!rhs.get_bool(ID_skip_initialize)) - { - exprt zero_element= - zero_initializer( - data.type().subtype(), - location, - ns, - get_message_handler()); - codet array_set(ID_array_set); - array_set.copy_to_operands(new_array_data_symbol, zero_element); - goto_programt::targett t_d=dest.add_instruction(OTHER); - t_d->code=array_set; - t_d->source_location=location; - } - - // multi-dimensional? - - if(rhs.operands().size()>=2) - { - // produce - // for(int i=0; i(rhs.type().subtype().find("#element_type")); - assert(sub_type.id()==ID_pointer); - sub_java_new.type()=sub_type; - - side_effect_exprt inc(ID_assign); - inc.operands().resize(2); - inc.op0()=tmp_i; - inc.op1()=plus_exprt(tmp_i, from_integer(1, tmp_i.type())); - - dereference_exprt deref_expr( - plus_exprt(data, tmp_i), data.type().subtype()); - - code_blockt for_body; - symbol_exprt init_sym = - new_tmp_symbol(sub_type, "subarray_init", tmp, location, ID_java) - .symbol_expr(); - - code_assignt init_subarray(init_sym, sub_java_new); - code_assignt assign_subarray( - deref_expr, - typecast_exprt(init_sym, deref_expr.type())); - for_body.move_to_operands(init_subarray); - for_body.move_to_operands(assign_subarray); - - for_loop.init()=code_assignt(tmp_i, from_integer(0, tmp_i.type())); - for_loop.cond()=binary_relation_exprt(tmp_i, ID_lt, rhs.op0()); - for_loop.iter()=inc; - for_loop.body()=for_body; - - convert(for_loop, tmp); - dest.destructive_append(tmp); - } -} - /// builds a goto program for object initialization after new void goto_convertt::cpp_new_initializer( const exprt &lhs, diff --git a/src/goto-programs/goto_convert.cpp b/src/goto-programs/goto_convert.cpp index b8ad4465554..c662c5a4c2f 100644 --- a/src/goto-programs/goto_convert.cpp +++ b/src/goto-programs/goto_convert.cpp @@ -753,30 +753,43 @@ void goto_convertt::convert_assign( Forall_operands(it, rhs) clean_expr(*it, dest); + // TODO: This should be done in a separate pass do_cpp_new(lhs, to_side_effect_expr(rhs), dest); } - else if(rhs.id()==ID_side_effect && - rhs.get(ID_statement)==ID_java_new) + else if( + rhs.id() == ID_side_effect && + (rhs.get(ID_statement) == ID_assign || + rhs.get(ID_statement) == ID_postincrement || + rhs.get(ID_statement) == ID_preincrement || + rhs.get(ID_statement) == ID_statement_expression)) { - Forall_operands(it, rhs) - clean_expr(*it, dest); + // handle above side effects + clean_expr(rhs, dest); - do_java_new(lhs, to_side_effect_expr(rhs), dest); - } - else if(rhs.id()==ID_side_effect && - rhs.get(ID_statement)==ID_java_new_array) - { - Forall_operands(it, rhs) - clean_expr(*it, dest); + if(lhs.id() == ID_typecast) + { + DATA_INVARIANT( + lhs.operands().size() == 1, "Typecast must have one operand"); - do_java_new_array(lhs, to_side_effect_expr(rhs), dest); + // add a typecast to the rhs + exprt new_rhs = rhs; + rhs.make_typecast(lhs.op0().type()); + + // remove typecast from lhs + exprt tmp = lhs.op0(); + lhs.swap(tmp); + } + + code_assignt new_assign(code); + new_assign.lhs() = lhs; + new_assign.rhs() = rhs; + + copy(new_assign, ASSIGN, dest); } - else if( - rhs.id() == ID_side_effect && - (rhs.get(ID_statement) == ID_allocate || - rhs.get(ID_statement) == ID_java_new_array_data)) + else if(rhs.id() == ID_side_effect) { - // just preserve + // preserve side effects that will be handled at later stages, + // such as allocate, new operators of other languages, e.g. java, etc Forall_operands(it, rhs) clean_expr(*it, dest); @@ -788,6 +801,7 @@ void goto_convertt::convert_assign( } else { + // do everything else clean_expr(rhs, dest); if(lhs.id()==ID_typecast) diff --git a/src/java_bytecode/Makefile b/src/java_bytecode/Makefile index cf6d7a5cc9d..13aa8e6c2ca 100644 --- a/src/java_bytecode/Makefile +++ b/src/java_bytecode/Makefile @@ -31,9 +31,10 @@ SRC = bytecode_info.cpp \ java_types.cpp \ java_utils.cpp \ mz_zip_archive.cpp \ - replace_java_nondet.cpp \ remove_exceptions.cpp \ remove_instanceof.cpp \ + remove_java_new.cpp \ + replace_java_nondet.cpp \ select_pointer_type.cpp \ # Empty last line diff --git a/src/java_bytecode/remove_java_new.cpp b/src/java_bytecode/remove_java_new.cpp new file mode 100644 index 00000000000..c1354c53e16 --- /dev/null +++ b/src/java_bytecode/remove_java_new.cpp @@ -0,0 +1,438 @@ +/*******************************************************************\ + +Module: Remove Java New Operators + +Author: Peter Schrammel + +\*******************************************************************/ + +/// \file +/// Remove Java New Operators + +#include "remove_java_new.h" + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +class remove_java_newt : public messaget +{ +public: + remove_java_newt( + symbol_table_baset &symbol_table, + message_handlert &_message_handler) + : messaget(_message_handler), symbol_table(symbol_table), ns(symbol_table) + { + } + + // Lower java_new for a single function + bool lower_java_new(goto_programt &); + + // Lower java_new for a single instruction + goto_programt::targett + lower_java_new(goto_programt &, goto_programt::targett); + +protected: + symbol_table_baset &symbol_table; + namespacet ns; + + goto_programt::targett lower_java_new( + exprt lhs, + side_effect_exprt rhs, + goto_programt &, + goto_programt::targett); + + goto_programt::targett lower_java_new_array( + exprt lhs, + side_effect_exprt rhs, + goto_programt &, + goto_programt::targett); +}; + +/// Replaces the instruction `lhs = new java_type` by +/// two instructions: +/// lhs = ALLOCATE(java_type) +/// *lhs = { zero-initialized java_type } +/// \param lhs: the lhs +/// \param rhs: the rhs +/// \param dest: the goto program to modify +/// \param target: the goto instruction to replace +/// \return the iterator advanced to the last of the inserted instructions +/// Note: we have to take a copy of `lhs` and `rhs` since they would suffer +/// destruction when replacing the instruction. +goto_programt::targett remove_java_newt::lower_java_new( + exprt lhs, + side_effect_exprt rhs, + goto_programt &dest, + goto_programt::targett target) +{ + PRECONDITION(!lhs.is_nil()); + PRECONDITION(rhs.operands().empty()); + PRECONDITION(rhs.type().id() == ID_pointer); + source_locationt location = rhs.source_location(); + typet object_type = rhs.type().subtype(); + + // build size expression + exprt object_size = size_of_expr(object_type, ns); + CHECK_RETURN(object_size.is_not_nil()); + + // we produce a malloc side-effect, which stays + side_effect_exprt malloc_expr(ID_allocate, rhs.type()); + malloc_expr.copy_to_operands(object_size); + // could use true and get rid of the code below + malloc_expr.copy_to_operands(false_exprt()); + target->make_assignment(code_assignt(lhs, malloc_expr)); + target->source_location = location; + + // zero-initialize the object + dereference_exprt deref(lhs, object_type); + exprt zero_object = + zero_initializer(object_type, location, ns, get_message_handler()); + set_class_identifier( + to_struct_expr(zero_object), ns, to_symbol_type(object_type)); + goto_programt::targett t_i = dest.insert_after(target); + t_i->make_assignment(code_assignt(deref, zero_object)); + t_i->source_location = location; + + return t_i; +} + +/// Replaces the instruction `lhs = new java_array_type` by +/// the following code: +/// lhs = ALLOCATE(java_type) +/// loops to initialize the elements (including multi-dimensional arrays) +/// \param lhs: the lhs +/// \param rhs: the rhs +/// \param dest: the goto program to modify +/// \param target: the goto instruction to replace +/// \return the iterator advanced to the last of the inserted instructions +/// Note: we have to take a copy of `lhs` and `rhs` since they would suffer +/// destruction when replacing the instruction. +goto_programt::targett remove_java_newt::lower_java_new_array( + exprt lhs, + side_effect_exprt rhs, + goto_programt &dest, + goto_programt::targett target) +{ + // lower_java_new_array without lhs not implemented + PRECONDITION(!lhs.is_nil()); + PRECONDITION(rhs.operands().size() >= 1); // one per dimension + PRECONDITION(rhs.type().id() == ID_pointer); + + source_locationt location = rhs.source_location(); + typet object_type = rhs.type().subtype(); + PRECONDITION(ns.follow(object_type).id() == ID_struct); + + // build size expression + exprt object_size = size_of_expr(object_type, ns); + CHECK_RETURN(!object_size.is_nil()); + + // we produce a malloc side-effect, which stays + side_effect_exprt malloc_expr(ID_allocate, rhs.type()); + malloc_expr.copy_to_operands(object_size); + // code use true and get rid of the code below + malloc_expr.copy_to_operands(false_exprt()); + + target->make_assignment(code_assignt(lhs, malloc_expr)); + target->source_location = location; + goto_programt::targett next = std::next(target); + + const struct_typet &struct_type = to_struct_type(ns.follow(object_type)); + + // Ideally we would have a check for `is_valid_java_array(struct_type)` but + // `is_valid_java_array is part of the java_bytecode module and we cannot + // introduce such dependencies. We do this simple check instead: + PRECONDITION(struct_type.components().size() == 3); + + // Init base class: + dereference_exprt deref(lhs, object_type); + exprt zero_object = + zero_initializer(object_type, location, ns, get_message_handler()); + set_class_identifier( + to_struct_expr(zero_object), ns, to_symbol_type(object_type)); + goto_programt::targett t_i = dest.insert_before(next); + t_i->make_assignment(code_assignt(deref, zero_object)); + t_i->source_location = location; + + // if it's an array, we need to set the length field + member_exprt length( + deref, + struct_type.components()[1].get_name(), + struct_type.components()[1].type()); + goto_programt::targett t_s = dest.insert_before(next); + t_s->make_assignment(code_assignt(length, rhs.op0())); + t_s->source_location = location; + + // we also need to allocate space for the data + member_exprt data( + deref, + struct_type.components()[2].get_name(), + struct_type.components()[2].type()); + + // Allocate a (struct realtype**) instead of a (void**) if possible. + const irept &given_element_type = object_type.find(ID_C_element_type); + typet allocate_data_type; + if(given_element_type.is_not_nil()) + { + allocate_data_type = + pointer_type(static_cast(given_element_type)); + } + else + allocate_data_type = data.type(); + + side_effect_exprt data_java_new_expr( + ID_java_new_array_data, allocate_data_type); + + // The instruction may specify a (hopefully small) upper bound on the + // array size, in which case we allocate a fixed-length array that may + // be larger than the `length` member rather than use a true variable- + // length array, which produces a more complex formula in the current + // backend. + const irept size_bound = rhs.find(ID_length_upper_bound); + if(size_bound.is_nil()) + data_java_new_expr.set(ID_size, rhs.op0()); + else + data_java_new_expr.set(ID_size, size_bound); + + // Must directly assign the new array to a temporary + // because goto-symex will notice `x=side_effect_exprt` but not + // `x=typecast_exprt(side_effect_exprt(...))` + symbol_exprt new_array_data_symbol = get_fresh_aux_symbol( + data_java_new_expr.type(), + id2string(target->function), + "tmp_new_data_array", + location, + ID_java, + symbol_table) + .symbol_expr(); + code_declt array_decl(new_array_data_symbol); + array_decl.add_source_location() = location; + goto_programt::targett t_array_decl = dest.insert_before(next); + t_array_decl->make_decl(array_decl); + t_array_decl->source_location = location; + goto_programt::targett t_p2 = dest.insert_before(next); + t_p2->make_assignment( + code_assignt(new_array_data_symbol, data_java_new_expr)); + t_p2->source_location = location; + + goto_programt::targett t_p = dest.insert_before(next); + exprt cast_java_new = new_array_data_symbol; + if(cast_java_new.type() != data.type()) + cast_java_new = typecast_exprt(cast_java_new, data.type()); + t_p->make_assignment(code_assignt(data, cast_java_new)); + t_p->source_location = location; + + // zero-initialize the data + if(!rhs.get_bool(ID_skip_initialize)) + { + exprt zero_element = zero_initializer( + data.type().subtype(), location, ns, get_message_handler()); + codet array_set(ID_array_set); + array_set.copy_to_operands(new_array_data_symbol, zero_element); + goto_programt::targett t_d = dest.insert_before(next); + t_d->make_other(array_set); + t_d->source_location = location; + } + + // multi-dimensional? + + if(rhs.operands().size() >= 2) + { + // produce + // for(int i=0; ifunction), + "tmp_index", + location, + ID_java, + symbol_table) + .symbol_expr(); + code_declt decl(tmp_i); + decl.add_source_location() = location; + goto_programt::targett t_decl = tmp.insert_before(tmp.instructions.begin()); + t_decl->make_decl(decl); + t_decl->source_location = location; + + code_fort for_loop; + + side_effect_exprt sub_java_new = rhs; + sub_java_new.operands().erase(sub_java_new.operands().begin()); + + // we already know that rhs has pointer type + typet sub_type = + static_cast(rhs.type().subtype().find("#element_type")); + CHECK_RETURN(sub_type.id() == ID_pointer); + sub_java_new.type() = sub_type; + + side_effect_exprt inc(ID_assign); + inc.operands().resize(2); + inc.op0() = tmp_i; + inc.op1() = plus_exprt(tmp_i, from_integer(1, tmp_i.type())); + + dereference_exprt deref_expr( + plus_exprt(data, tmp_i), data.type().subtype()); + + code_blockt for_body; + symbol_exprt init_sym = get_fresh_aux_symbol( + sub_type, + id2string(target->function), + "subarray_init", + location, + ID_java, + symbol_table) + .symbol_expr(); + code_declt init_decl(init_sym); + init_decl.add_source_location() = location; + for_body.move_to_operands(init_decl); + + code_assignt init_subarray(init_sym, sub_java_new); + code_assignt assign_subarray( + deref_expr, typecast_exprt(init_sym, deref_expr.type())); + for_body.move_to_operands(init_subarray); + for_body.move_to_operands(assign_subarray); + + for_loop.init() = code_assignt(tmp_i, from_integer(0, tmp_i.type())); + for_loop.cond() = binary_relation_exprt(tmp_i, ID_lt, rhs.op0()); + for_loop.iter() = inc; + for_loop.body() = for_body; + + goto_convert(for_loop, symbol_table, tmp, get_message_handler()); + + // lower new side effects recursively + lower_java_new(tmp); + + dest.destructive_insert(next, tmp); + } + + return std::prev(next); +} + +/// Replace every java_new or java_new_array by a malloc side-effect +/// and zero initialization. +/// \param goto_program: program to process +/// \param target: instruction to check for java_new expressions +/// \return true if a replacement has been made +goto_programt::targett remove_java_newt::lower_java_new( + goto_programt &goto_program, + goto_programt::targett target) +{ + const auto maybe_code_assign = + expr_try_dynamic_cast(target->code); + if(!maybe_code_assign) + return target; + + const exprt &lhs = maybe_code_assign->lhs(); + const exprt &rhs = maybe_code_assign->rhs(); + + if(rhs.id() == ID_side_effect && rhs.get(ID_statement) == ID_java_new) + { + return lower_java_new(lhs, to_side_effect_expr(rhs), goto_program, target); + } + + if(rhs.id() == ID_side_effect && rhs.get(ID_statement) == ID_java_new_array) + { + return lower_java_new_array( + lhs, to_side_effect_expr(rhs), goto_program, target); + } + + return target; +} + +/// Replace every java_new or java_new_array by a malloc side-effect +/// and zero initialization. +/// Extra auxiliary variables may be introduced into symbol_table. +/// \param goto_program: The function body to work on. +/// \return true if one or more java_new expressions have been replaced +bool remove_java_newt::lower_java_new(goto_programt &goto_program) +{ + bool changed = false; + for(goto_programt::instructionst::iterator target = + goto_program.instructions.begin(); + target != goto_program.instructions.end(); + ++target) + { + goto_programt::targett new_target = lower_java_new(goto_program, target); + changed = changed || new_target == target; + target = new_target; + } + if(!changed) + return false; + goto_program.update(); + return true; +} + +/// Replace every java_new or java_new_array by a malloc side-effect +/// and zero initialization. +/// \remarks Extra auxiliary variables may be introduced into symbol_table. +/// \param target: The instruction to work on. +/// \param goto_program: The function body containing the instruction. +/// \param symbol_table: The symbol table to add symbols to. +/// \param message_handler: a message handler +void remove_java_new( + goto_programt::targett target, + goto_programt &goto_program, + symbol_table_baset &symbol_table, + message_handlert &message_handler) +{ + remove_java_newt rem(symbol_table, message_handler); + rem.lower_java_new(goto_program, target); +} + +/// Replace every java_new or java_new_array by a malloc side-effect +/// and zero initialization. +/// \remarks Extra auxiliary variables may be introduced into symbol_table. +/// \param function: The function to work on. +/// \param symbol_table: The symbol table to add symbols to. +/// \param message_handler: a message handler +void remove_java_new( + goto_functionst::goto_functiont &function, + symbol_table_baset &symbol_table, + message_handlert &message_handler) +{ + remove_java_newt rem(symbol_table, message_handler); + rem.lower_java_new(function.body); +} + +/// Replace every java_new or java_new_array by a malloc side-effect +/// and zero initialization. +/// \remarks Extra auxiliary variables may be introduced into symbol_table. +/// \param goto_functions: The functions to work on. +/// \param symbol_table: The symbol table to add symbols to. +/// \param message_handler: a message handler +void remove_java_new( + goto_functionst &goto_functions, + symbol_table_baset &symbol_table, + message_handlert &message_handler) +{ + remove_java_newt rem(symbol_table, message_handler); + bool changed = false; + for(auto &f : goto_functions.function_map) + changed = rem.lower_java_new(f.second.body) || changed; + if(changed) + goto_functions.compute_location_numbers(); +} + +/// Replace every java_new or java_new_array by a malloc side-effect +/// and zero initialization. +/// \remarks Extra auxiliary variables may be introduced into symbol_table. +/// \param goto_model: The functions to work on and the symbol table to add +/// symbols to. +/// \param message_handler: a message handler +void remove_java_new(goto_modelt &goto_model, message_handlert &message_handler) +{ + remove_java_new( + goto_model.goto_functions, goto_model.symbol_table, message_handler); +} diff --git a/src/java_bytecode/remove_java_new.h b/src/java_bytecode/remove_java_new.h new file mode 100644 index 00000000000..a40b98b7607 --- /dev/null +++ b/src/java_bytecode/remove_java_new.h @@ -0,0 +1,40 @@ +/*******************************************************************\ + +Module: Remove Java New Operators + +Author: Peter Schrammel + +\*******************************************************************/ + +/// \file +/// Remove Java New Operators + +#ifndef CPROVER_JAVA_BYTECODE_REMOVE_JAVA_NEW_H +#define CPROVER_JAVA_BYTECODE_REMOVE_JAVA_NEW_H + +#include + +#include +#include + +class message_handlert; + +void remove_java_new( + goto_programt::targett target, + goto_programt &goto_program, + symbol_table_baset &symbol_table, + message_handlert &_message_handler); + +void remove_java_new( + goto_functionst::goto_functiont &function, + symbol_table_baset &symbol_table, + message_handlert &_message_handler); + +void remove_java_new( + goto_functionst &goto_functions, + symbol_table_baset &symbol_table, + message_handlert &_message_handler); + +void remove_java_new(goto_modelt &model, message_handlert &_message_handler); + +#endif // CPROVER_JAVA_BYTECODE_REMOVE_JAVA_NEW_H From 9ecb010b99ed3011ca4e1bf10e7e1ccbd696f2eb Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Thu, 26 Apr 2018 15:00:35 +0100 Subject: [PATCH 68/93] more files to ignore --- .gitignore | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4636f5a8380..cbe1112cbeb 100644 --- a/.gitignore +++ b/.gitignore @@ -30,8 +30,10 @@ Release/* *.lib src/ansi-c/arm_builtin_headers.inc src/ansi-c/clang_builtin_headers.inc +src/ansi-c/cprover_builtin_headers.inc src/ansi-c/cprover_library.inc src/ansi-c/cw_builtin_headers.inc +src/ansi-c/gcc_builtin_headers_types.inc src/ansi-c/gcc_builtin_headers_alpha.inc src/ansi-c/gcc_builtin_headers_arm.inc src/ansi-c/gcc_builtin_headers_generic.inc @@ -46,6 +48,7 @@ src/ansi-c/gcc_builtin_headers_tm.inc src/ansi-c/gcc_builtin_headers_mips.inc src/ansi-c/gcc_builtin_headers_power.inc src/ansi-c/gcc_builtin_headers_ubsan.inc +src/ansi-c/windows_builtin_headers.inc src/java_bytecode/java_core_models.inc # regression/test files @@ -104,8 +107,8 @@ src/goto-instrument/goto-instrument.exe src/jbmc/jbmc src/musketeer/musketeer src/musketeer/musketeer.exe -src/solvers/smt2/smt2_solver -src/solvers/smt2/smt2_solver.exe +src/solvers/smt2_solver +src/solvers/smt2_solver.exe src/symex/symex src/symex/symex.exe src/goto-diff/goto-diff From eeae6976d84a17066ab0a8455ea8aa0ce9254952 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Wed, 25 Apr 2018 22:23:21 +0100 Subject: [PATCH 69/93] Use remove_java_new --- src/jbmc/jbmc_parse_options.cpp | 6 +++++- unit/pointer-analysis/custom_value_set_analysis.cpp | 10 +++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/jbmc/jbmc_parse_options.cpp b/src/jbmc/jbmc_parse_options.cpp index 4a371001851..031d7aec587 100644 --- a/src/jbmc/jbmc_parse_options.cpp +++ b/src/jbmc/jbmc_parse_options.cpp @@ -53,8 +53,9 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include #include +#include +#include #include #include @@ -763,6 +764,9 @@ void jbmc_parse_optionst::process_goto_function( // add generic checks goto_check(ns, options, ID_java, function.get_goto_function()); + // Replace Java new side effects + remove_java_new(goto_function, symbol_table, get_message_handler()); + // checks don't know about adjusted float expressions adjust_float_expressions(goto_function, ns); diff --git a/unit/pointer-analysis/custom_value_set_analysis.cpp b/unit/pointer-analysis/custom_value_set_analysis.cpp index 5fdc3197f38..01791c36528 100644 --- a/unit/pointer-analysis/custom_value_set_analysis.cpp +++ b/unit/pointer-analysis/custom_value_set_analysis.cpp @@ -8,13 +8,14 @@ Author: Chris Smowton, chris@smowton.net #include -#include -#include -#include #include +#include #include #include +#include +#include #include +#include /// An example customised value_sett. It makes a series of small changes /// to the underlying value_sett logic, which can then be verified by the @@ -183,6 +184,9 @@ SCENARIO("test_value_set_analysis", goto_modelt goto_model= initialize_goto_model(command_line, null_output); + null_message_handlert message_handler; + remove_java_new(goto_model, message_handler); + namespacet ns(goto_model.symbol_table); // Fully inline the test program, to avoid VSA conflating From e3451db06c2e13c6eab8fba9145c1378092f2836 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 7 Apr 2018 12:51:06 +0100 Subject: [PATCH 70/93] Remove java_bytecode deps from Makefiles --- src/clobber/CMakeLists.txt | 1 - src/clobber/Makefile | 2 +- src/goto-cc/CMakeLists.txt | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/clobber/CMakeLists.txt b/src/clobber/CMakeLists.txt index 384ae51824e..2e4803df7e2 100644 --- a/src/clobber/CMakeLists.txt +++ b/src/clobber/CMakeLists.txt @@ -25,7 +25,6 @@ target_link_libraries(clobber-lib ) add_if_library(clobber-lib bv_refinement) -add_if_library(clobber-lib java_bytecode) add_if_library(clobber-lib specc) add_if_library(clobber-lib php) diff --git a/src/clobber/Makefile b/src/clobber/Makefile index 74a133782c6..d9b9f09de1c 100644 --- a/src/clobber/Makefile +++ b/src/clobber/Makefile @@ -1,9 +1,9 @@ SRC = clobber_main.cpp \ clobber_parse_options.cpp \ # Empty last line + OBJ += ../ansi-c/ansi-c$(LIBEXT) \ ../cpp/cpp$(LIBEXT) \ - ../java_bytecode/java_bytecode$(LIBEXT) \ ../linking/linking$(LIBEXT) \ ../big-int/big-int$(LIBEXT) \ ../goto-programs/goto-programs$(LIBEXT) \ diff --git a/src/goto-cc/CMakeLists.txt b/src/goto-cc/CMakeLists.txt index 8259d960561..75b8a7f860c 100644 --- a/src/goto-cc/CMakeLists.txt +++ b/src/goto-cc/CMakeLists.txt @@ -19,7 +19,6 @@ target_link_libraries(goto-cc-lib langapi ) -add_if_library(goto-cc-lib java_bytecode) add_if_library(goto-cc-lib jsil) # Executable From 5590489083614750cf5db44ea6c4b7d8257c01d8 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Thu, 26 Apr 2018 16:05:47 +0100 Subject: [PATCH 71/93] use optional instead of -1 in cmdlinet --- src/goto-cc/goto_cc_cmdline.cpp | 6 +- src/goto-cc/ms_cl_cmdline.cpp | 14 ++-- src/util/cmdline.cpp | 110 +++++++++++++++++++------------- src/util/cmdline.h | 8 ++- 4 files changed, 82 insertions(+), 56 deletions(-) diff --git a/src/goto-cc/goto_cc_cmdline.cpp b/src/goto-cc/goto_cc_cmdline.cpp index ac86ee38551..f1b933a2847 100644 --- a/src/goto-cc/goto_cc_cmdline.cpp +++ b/src/goto-cc/goto_cc_cmdline.cpp @@ -65,7 +65,7 @@ bool goto_cc_cmdlinet::prefix_in_list( std::size_t goto_cc_cmdlinet::get_optnr(const std::string &opt_string) { - int optnr; + optionalt optnr; cmdlinet::optiont option; if(has_prefix(opt_string, "--")) // starts with -- ? @@ -107,13 +107,13 @@ std::size_t goto_cc_cmdlinet::get_optnr(const std::string &opt_string) } // new? - if(optnr==-1) + if(!optnr.has_value()) { options.push_back(option); return options.size()-1; } - return optnr; + return *optnr; } void goto_cc_cmdlinet::add_infile_arg(const std::string &arg) diff --git a/src/goto-cc/ms_cl_cmdline.cpp b/src/goto-cc/ms_cl_cmdline.cpp index cdc9458bb0c..7364beca6ba 100644 --- a/src/goto-cc/ms_cl_cmdline.cpp +++ b/src/goto-cc/ms_cl_cmdline.cpp @@ -425,7 +425,7 @@ void ms_cl_cmdlinet::process_cl_option(const std::string &s) if(std::string(s, 1, std::string::npos)==ms_cl_flags[j]) { cmdlinet::optiont option; - int optnr; + optionalt optnr; if(s.size()==2) { @@ -442,13 +442,13 @@ void ms_cl_cmdlinet::process_cl_option(const std::string &s) optnr=getoptnr(option.optstring); } - if(optnr==-1) + if(!optnr.has_value()) { options.push_back(option); optnr=options.size()-1; } - options[optnr].isset=true; + options[*optnr].isset=true; return; } } @@ -461,7 +461,7 @@ void ms_cl_cmdlinet::process_cl_option(const std::string &s) { cmdlinet::optiont option; - int optnr; + optionalt optnr; if(ms_cl_prefix.size()==1) { @@ -478,14 +478,14 @@ void ms_cl_cmdlinet::process_cl_option(const std::string &s) optnr=getoptnr(option.optstring); } - if(optnr==-1) + if(!optnr.has_value()) { options.push_back(option); optnr=options.size()-1; } - options[optnr].isset=true; - options[optnr].values.push_back( + options[*optnr].isset=true; + options[*optnr].values.push_back( std::string(s, ms_cl_prefix.size()+1, std::string::npos)); return; diff --git a/src/util/cmdline.cpp b/src/util/cmdline.cpp index 9477d8d4a6c..b022fdce78d 100644 --- a/src/util/cmdline.cpp +++ b/src/util/cmdline.cpp @@ -26,92 +26,114 @@ void cmdlinet::clear() bool cmdlinet::isset(char option) const { - int i=getoptnr(option); - if(i<0) + auto i=getoptnr(option); + if(i.has_value()) + return options[*i].isset; + else return false; - return options[i].isset; } bool cmdlinet::isset(const char *option) const { - int i=getoptnr(option); - if(i<0) + auto i=getoptnr(option); + if(i.has_value()) + return options[*i].isset; + else return false; - return options[i].isset; } std::string cmdlinet::get_value(char option) const { - int i=getoptnr(option); - if(i<0) - return ""; - if(options[i].values.empty()) + auto i=getoptnr(option); + + if(i.has_value()) + { + if(options[*i].values.empty()) + return ""; + else + return options[*i].values.front(); + } + else return ""; - return options[i].values.front(); } void cmdlinet::set(const std::string &option) { - int i=getoptnr(option); - if(i<0) - return; // ignore - options[i].isset=true; + auto i=getoptnr(option); + + if(i.has_value()) + options[*i].isset=true; + + // otherwise ignore } void cmdlinet::set(const std::string &option, const std::string &value) { - int i=getoptnr(option); - if(i<0) - return; // ignore - options[i].isset=true; - options[i].values.push_back(value); + auto i=getoptnr(option); + + if(i.has_value()) + { + options[*i].isset=true; + options[*i].values.push_back(value); + } + + // otherwise ignore } static std::list immutable_empty_list; const std::list &cmdlinet::get_values(char option) const { - int i=getoptnr(option); - if(i<0) + auto i=getoptnr(option); + + if(i.has_value()) + return options[*i].values; + else return immutable_empty_list; - return options[i].values; } std::string cmdlinet::get_value(const char *option) const { - int i=getoptnr(option); - if(i<0) - return ""; - if(options[i].values.empty()) + auto i=getoptnr(option); + + if(i.has_value()) + { + if(options[*i].values.empty()) + return ""; + else + return options[*i].values.front(); + } + else return ""; - return options[i].values.front(); } const std::list &cmdlinet::get_values( const std::string &option) const { - int i=getoptnr(option); - if(i<0) + auto i=getoptnr(option); + + if(i.has_value()) + return options[*i].values; + else return immutable_empty_list; - return options[i].values; } -int cmdlinet::getoptnr(char option) const +optionalt cmdlinet::getoptnr(char option) const { for(std::size_t i=0; i(); } -int cmdlinet::getoptnr(const std::string &option) const +optionalt cmdlinet::getoptnr(const std::string &option) const { for(std::size_t i=0; i(); } bool cmdlinet::parse(int argc, const char **argv, const char *optstring) @@ -165,7 +187,7 @@ bool cmdlinet::parse(int argc, const char **argv, const char *optstring) args.push_back(argv[i]); else { - int optnr; + optionalt optnr; if(argv[i][1]!=0 && argv[i][2]==0) optnr=getoptnr(argv[i][1]); // single-letter option -X @@ -177,29 +199,31 @@ bool cmdlinet::parse(int argc, const char **argv, const char *optstring) // We first try single-letter. optnr=getoptnr(argv[i][1]); - if(optnr<0) // try multi-letter + if(!optnr.has_value()) // try multi-letter optnr=getoptnr(argv[i]+1); } - if(optnr<0) + if(!optnr.has_value()) { unknown_arg=argv[i]; return true; } - options[optnr].isset=true; - if(options[optnr].hasval) + + options[*optnr].isset=true; + + if(options[*optnr].hasval) { - if(argv[i][2]==0 || options[optnr].islong) + if(argv[i][2]==0 || options[*optnr].islong) { i++; if(i==argc) return true; if(argv[i][0]=='-' && argv[i][1]!=0) return true; - options[optnr].values.push_back(argv[i]); + options[*optnr].values.push_back(argv[i]); } else - options[optnr].values.push_back(argv[i]+2); + options[*optnr].values.push_back(argv[i]+2); } } } diff --git a/src/util/cmdline.h b/src/util/cmdline.h index 2d58daa8d44..b395e024f7f 100644 --- a/src/util/cmdline.h +++ b/src/util/cmdline.h @@ -14,6 +14,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include "optional.h" + class cmdlinet { public: @@ -53,13 +55,13 @@ class cmdlinet hasval(false), islong(false), optchar(0) - {} + {} }; std::vector options; - int getoptnr(char option) const; - int getoptnr(const std::string &option) const; + optionalt getoptnr(char option) const; + optionalt getoptnr(const std::string &option) const; }; #endif // CPROVER_UTIL_CMDLINE_H From c57627cfd940bcdecee55f4db13b6d7a82480142 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Thu, 26 Apr 2018 18:18:49 +0000 Subject: [PATCH 72/93] Use iosfwd instead of ostream where possible --- src/analyses/goto_rw.h | 2 +- src/cbmc/symex_coverage.h | 2 +- src/goto-analyzer/static_show_domain.h | 2 +- src/goto-analyzer/static_simplifier.h | 2 +- src/goto-analyzer/static_verifier.h | 2 +- src/goto-instrument/object_id.h | 2 +- src/jsil/jsil_parse_tree.cpp | 2 ++ src/jsil/jsil_parse_tree.h | 2 +- src/util/graph.h | 2 +- src/util/json_stream.h | 2 +- src/util/string_utils.h | 2 +- src/xmllang/graphml.h | 3 +-- 12 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/analyses/goto_rw.h b/src/analyses/goto_rw.h index 02f17a7af16..bc1c848413f 100644 --- a/src/analyses/goto_rw.h +++ b/src/analyses/goto_rw.h @@ -13,7 +13,7 @@ Date: April 2010 #define CPROVER_ANALYSES_GOTO_RW_H #include -#include +#include #include #include // unique_ptr diff --git a/src/cbmc/symex_coverage.h b/src/cbmc/symex_coverage.h index b7556b1087b..9bba52fd84b 100644 --- a/src/cbmc/symex_coverage.h +++ b/src/cbmc/symex_coverage.h @@ -15,7 +15,7 @@ Date: March 2016 #define CPROVER_CBMC_SYMEX_COVERAGE_H #include -#include +#include #include #include diff --git a/src/goto-analyzer/static_show_domain.h b/src/goto-analyzer/static_show_domain.h index 5284cc6a9ec..1b2c3ee3772 100644 --- a/src/goto-analyzer/static_show_domain.h +++ b/src/goto-analyzer/static_show_domain.h @@ -9,7 +9,7 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk #ifndef CPROVER_GOTO_ANALYZER_STATIC_SHOW_DOMAIN_H #define CPROVER_GOTO_ANALYZER_STATIC_SHOW_DOMAIN_H -#include +#include #include #include diff --git a/src/goto-analyzer/static_simplifier.h b/src/goto-analyzer/static_simplifier.h index ee810bf8793..59e741fba83 100644 --- a/src/goto-analyzer/static_simplifier.h +++ b/src/goto-analyzer/static_simplifier.h @@ -9,7 +9,7 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk #ifndef CPROVER_GOTO_ANALYZER_STATIC_SIMPLIFIER_H #define CPROVER_GOTO_ANALYZER_STATIC_SIMPLIFIER_H -#include +#include #include #include diff --git a/src/goto-analyzer/static_verifier.h b/src/goto-analyzer/static_verifier.h index 77eeacbe527..e71bdfbb45c 100644 --- a/src/goto-analyzer/static_verifier.h +++ b/src/goto-analyzer/static_verifier.h @@ -9,7 +9,7 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk #ifndef CPROVER_GOTO_ANALYZER_STATIC_VERIFIER_H #define CPROVER_GOTO_ANALYZER_STATIC_VERIFIER_H -#include +#include #include #include diff --git a/src/goto-instrument/object_id.h b/src/goto-instrument/object_id.h index f7c597a798b..98e4b03033b 100644 --- a/src/goto-instrument/object_id.h +++ b/src/goto-instrument/object_id.h @@ -13,7 +13,7 @@ Author: Daniel Kroening, kroening@kroening.com #define CPROVER_GOTO_INSTRUMENT_OBJECT_ID_H #include -#include +#include #include #include diff --git a/src/jsil/jsil_parse_tree.cpp b/src/jsil/jsil_parse_tree.cpp index 093a62f4fb9..8263b843c98 100644 --- a/src/jsil/jsil_parse_tree.cpp +++ b/src/jsil/jsil_parse_tree.cpp @@ -11,6 +11,8 @@ Author: Michael Tautschnig, tautschn@amazon.com #include "jsil_parse_tree.h" +#include + #include #include "jsil_types.h" diff --git a/src/jsil/jsil_parse_tree.h b/src/jsil/jsil_parse_tree.h index 55ee57de51b..f5410564783 100644 --- a/src/jsil/jsil_parse_tree.h +++ b/src/jsil/jsil_parse_tree.h @@ -12,7 +12,7 @@ Author: Michael Tautschnig, tautschn@amazon.com #ifndef CPROVER_JSIL_JSIL_PARSE_TREE_H #define CPROVER_JSIL_JSIL_PARSE_TREE_H -#include +#include #include #include diff --git a/src/util/graph.h b/src/util/graph.h index 16af29ea634..85ad33c448d 100644 --- a/src/util/graph.h +++ b/src/util/graph.h @@ -16,7 +16,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include -#include +#include #include #include #include diff --git a/src/util/json_stream.h b/src/util/json_stream.h index 4f1541d0496..f27e360c9a3 100644 --- a/src/util/json_stream.h +++ b/src/util/json_stream.h @@ -10,7 +10,7 @@ Author: Peter Schrammel #define CPROVER_UTIL_JSON_STREAM_H #include -#include +#include #include "json.h" #include "invariant.h" diff --git a/src/util/string_utils.h b/src/util/string_utils.h index 87dd742d666..23d3d6ea6ba 100644 --- a/src/util/string_utils.h +++ b/src/util/string_utils.h @@ -10,7 +10,7 @@ Author: Daniel Poetzl #ifndef CPROVER_UTIL_STRING_UTILS_H #define CPROVER_UTIL_STRING_UTILS_H -#include +#include #include #include diff --git a/src/xmllang/graphml.h b/src/xmllang/graphml.h index 3b399d48c3b..f86dac5648e 100644 --- a/src/xmllang/graphml.h +++ b/src/xmllang/graphml.h @@ -12,8 +12,7 @@ Author: Michael Tautschnig, mt@eecs.qmul.ac.uk #ifndef CPROVER_XMLLANG_GRAPHML_H #define CPROVER_XMLLANG_GRAPHML_H -#include -#include +#include #include #include From 60bcdb674a7d3c1dc8b0b5fd3feb6706755e021e Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Thu, 26 Apr 2018 18:21:43 +0000 Subject: [PATCH 73/93] Use a single global INITIALIZE_FUNCTION macro instead of __CPROVER_initialize --- src/ansi-c/ansi_c_entry_point.cpp | 3 ++- src/ansi-c/ansi_c_internal_additions.cpp | 4 +++- src/cbmc/bmc.cpp | 4 +++- src/cbmc/symex_coverage.cpp | 4 +++- src/cpp/cpp_internal_additions.cpp | 4 +++- src/goto-cc/compile.cpp | 4 +++- src/goto-cc/linker_script_merge.cpp | 7 ++++--- src/goto-instrument/call_sequences.cpp | 4 +++- src/goto-instrument/code_contracts.cpp | 4 +++- src/goto-instrument/cover_filter.cpp | 6 ++---- src/goto-instrument/dump_c.cpp | 4 +++- src/goto-instrument/interrupt.cpp | 12 ++---------- src/goto-instrument/mmio.cpp | 4 ++-- src/goto-instrument/nondet_static.cpp | 4 +++- src/goto-instrument/race_check.cpp | 4 +++- src/goto-instrument/stack_depth.cpp | 11 ++++++----- src/goto-instrument/wmm/goto2graph.cpp | 4 +++- src/goto-instrument/wmm/shared_buffers.cpp | 5 ++++- src/goto-instrument/wmm/weak_memory.cpp | 4 +++- src/java_bytecode/java_entry_point.cpp | 3 ++- src/jsil/jsil_entry_point.cpp | 12 ++++++------ src/linking/remove_internal_symbols.cpp | 4 +++- 22 files changed, 69 insertions(+), 46 deletions(-) diff --git a/src/ansi-c/ansi_c_entry_point.cpp b/src/ansi-c/ansi_c_entry_point.cpp index a632d616fc2..04da6131608 100644 --- a/src/ansi-c/ansi_c_entry_point.cpp +++ b/src/ansi-c/ansi_c_entry_point.cpp @@ -23,6 +23,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include + #include #include "c_nondet_symbol_factory.h" @@ -217,7 +218,7 @@ bool generate_ansi_c_start_function( if(init_it==symbol_table.symbols.end()) { messaget message(message_handler); - message.error() << "failed to find " CPROVER_PREFIX "initialize symbol" + message.error() << "failed to find " INITIALIZE_FUNCTION " symbol" << messaget::eom; return true; } diff --git a/src/ansi-c/ansi_c_internal_additions.cpp b/src/ansi-c/ansi_c_internal_additions.cpp index 845e2197e84..47ef1c503f5 100644 --- a/src/ansi-c/ansi_c_internal_additions.cpp +++ b/src/ansi-c/ansi_c_internal_additions.cpp @@ -10,6 +10,8 @@ Author: Daniel Kroening, kroening@kroening.com #include +#include + const char gcc_builtin_headers_types[]= "# 1 \"gcc_builtin_headers_types.h\"\n" #include "gcc_builtin_headers_types.inc" @@ -172,7 +174,7 @@ void ansi_c_internal_additions(std::string &code) "\n" // This function needs to be declared, or otherwise can't be called // by the entry-point construction. - "void __CPROVER_initialize(void);\n" + "void " INITIALIZE_FUNCTION "(void);\n" "\n"; // GCC junk stuff, also for CLANG and ARM diff --git a/src/cbmc/bmc.cpp b/src/cbmc/bmc.cpp index 37bedbed2f4..e0af60274f5 100644 --- a/src/cbmc/bmc.cpp +++ b/src/cbmc/bmc.cpp @@ -42,6 +42,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include + #include "cbmc_solvers.h" #include "counterexample_beautification.h" #include "fault_localization.h" @@ -338,7 +340,7 @@ void bmct::setup() { const symbolt *init_symbol; - if(!ns.lookup(CPROVER_PREFIX "initialize", init_symbol)) + if(!ns.lookup(INITIALIZE_FUNCTION, init_symbol)) symex.language_mode=init_symbol->mode; } diff --git a/src/cbmc/symex_coverage.cpp b/src/cbmc/symex_coverage.cpp index fec36dd1f5f..77f7fe93ba6 100644 --- a/src/cbmc/symex_coverage.cpp +++ b/src/cbmc/symex_coverage.cpp @@ -29,6 +29,8 @@ Date: March 2016 #include #include +#include + class coverage_recordt { public: @@ -313,7 +315,7 @@ void symex_coveraget::compute_overall_coverage( { if(!gf_it->second.body_available() || gf_it->first==goto_functions.entry_point() || - gf_it->first==CPROVER_PREFIX "initialize") + gf_it->first == INITIALIZE_FUNCTION) continue; goto_program_coverage_recordt func_cov(ns, gf_it, coverage); diff --git a/src/cpp/cpp_internal_additions.cpp b/src/cpp/cpp_internal_additions.cpp index 19260f6ac24..85363a59b69 100644 --- a/src/cpp/cpp_internal_additions.cpp +++ b/src/cpp/cpp_internal_additions.cpp @@ -14,6 +14,8 @@ Author: Daniel Kroening, kroening@kroening.com #include +#include + std::string c2cpp(const std::string &s) { std::string result; @@ -75,7 +77,7 @@ void cpp_internal_additions(std::ostream &out) // CPROVER extensions out << "extern \"C\" const unsigned __CPROVER::constant_infinity_uint;\n"; - out << "extern \"C\" void __CPROVER_initialize();" << '\n'; + out << "extern \"C\" void " INITIALIZE_FUNCTION "();" << '\n'; out << "extern \"C\" void __CPROVER::input(const char *id, ...);" << '\n'; out << "extern \"C\" void __CPROVER::output(const char *id, ...);" << '\n'; out << "extern \"C\" void __CPROVER::cover(bool condition);" << '\n'; diff --git a/src/goto-cc/compile.cpp b/src/goto-cc/compile.cpp index 4f84f36bc3f..c092f940f95 100644 --- a/src/goto-cc/compile.cpp +++ b/src/goto-cc/compile.cpp @@ -41,6 +41,8 @@ Date: June 2006 #include +#include + #include #define DOTGRAPHSETTINGS "color=black;" \ @@ -372,7 +374,7 @@ bool compilet::link() // new symbols may have been added to a previously linked file // make sure a new entry point is created that contains all // static initializers - compiled_functions.function_map.erase("__CPROVER_initialize"); + compiled_functions.function_map.erase(INITIALIZE_FUNCTION); symbol_table.remove(goto_functionst::entry_point()); compiled_functions.function_map.erase(goto_functionst::entry_point()); diff --git a/src/goto-cc/linker_script_merge.cpp b/src/goto-cc/linker_script_merge.cpp index 72ec71f7ad3..c7ede967768 100644 --- a/src/goto-cc/linker_script_merge.cpp +++ b/src/goto-cc/linker_script_merge.cpp @@ -24,6 +24,7 @@ Author: Kareem Khazem , 2017 #include #include +#include #include #include @@ -78,10 +79,10 @@ int linker_script_merget::add_linker_script_definitions() fail=1; linker_valuest linker_values; - const auto &pair=original_gf.function_map.find(CPROVER_PREFIX "initialize"); + const auto &pair=original_gf.function_map.find(INITIALIZE_FUNCTION); if(pair==original_gf.function_map.end()) { - error() << "No " << CPROVER_PREFIX "initialize found in goto_functions" + error() << "No " << INITIALIZE_FUNCTION << " found in goto_functions" << eom; return fail; } @@ -93,7 +94,7 @@ int linker_script_merget::add_linker_script_definitions() linker_values); if(fail!=0) { - error() << "Could not add linkerscript defs to __CPROVER_initialize" << eom; + error() << "Could not add linkerscript defs to " INITIALIZE_FUNCTION << eom; return fail; } diff --git a/src/goto-instrument/call_sequences.cpp b/src/goto-instrument/call_sequences.cpp index c188828768b..82da31087b8 100644 --- a/src/goto-instrument/call_sequences.cpp +++ b/src/goto-instrument/call_sequences.cpp @@ -24,6 +24,8 @@ Date: April 2013 #include +#include + void show_call_sequences( const irep_idt &caller, const goto_programt &goto_program) @@ -286,7 +288,7 @@ static void list_calls_and_arguments( continue; const irep_idt &identifier=to_symbol_expr(f).get_identifier(); - if(identifier=="__CPROVER_initialize") + if(identifier == INITIALIZE_FUNCTION) continue; std::string name=from_expr(ns, identifier, f); diff --git a/src/goto-instrument/code_contracts.cpp b/src/goto-instrument/code_contracts.cpp index 256149084eb..16f3ebe8312 100644 --- a/src/goto-instrument/code_contracts.cpp +++ b/src/goto-instrument/code_contracts.cpp @@ -21,6 +21,8 @@ Date: February 2016 #include +#include + #include "loop_utils.h" class code_contractst @@ -385,7 +387,7 @@ void code_contractst::operator()() code_contracts(it->second); goto_functionst::function_mapt::iterator i_it= - goto_functions.function_map.find(CPROVER_PREFIX "initialize"); + goto_functions.function_map.find(INITIALIZE_FUNCTION); assert(i_it!=goto_functions.function_map.end()); for(const auto &contract : summarized) diff --git a/src/goto-instrument/cover_filter.cpp b/src/goto-instrument/cover_filter.cpp index 3ca83843170..2c9c6c3f6d6 100644 --- a/src/goto-instrument/cover_filter.cpp +++ b/src/goto-instrument/cover_filter.cpp @@ -11,9 +11,7 @@ Author: Peter Schrammel #include "cover_filter.h" -#include - -#include +#include /// Filter out functions that are not considered provided by the user /// \param identifier: a function name @@ -26,7 +24,7 @@ bool internal_functions_filtert::operator()( if(identifier == goto_functionst::entry_point()) return false; - if(identifier == (CPROVER_PREFIX "initialize")) + if(identifier == INITIALIZE_FUNCTION) return false; if(goto_function.is_hidden()) diff --git a/src/goto-instrument/dump_c.cpp b/src/goto-instrument/dump_c.cpp index c36cca90179..c51a6859d3e 100644 --- a/src/goto-instrument/dump_c.cpp +++ b/src/goto-instrument/dump_c.cpp @@ -26,6 +26,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include + #include "goto_program2code.h" #include "dump_c_class.h" @@ -953,7 +955,7 @@ void dump_ct::cleanup_harness(code_blockt &b) symbol_exprt &s=to_symbol_expr(func); if(s.get_identifier()==ID_main) s.set_identifier(CPROVER_PREFIX+id2string(ID_main)); - else if(s.get_identifier()==CPROVER_PREFIX "initialize") + else if(s.get_identifier() == INITIALIZE_FUNCTION) continue; } } diff --git a/src/goto-instrument/interrupt.cpp b/src/goto-instrument/interrupt.cpp index 23bf63eb1a4..4d3416a3b38 100644 --- a/src/goto-instrument/interrupt.cpp +++ b/src/goto-instrument/interrupt.cpp @@ -13,15 +13,7 @@ Date: September 2011 #include "interrupt.h" -#include -#include -#include -#include -#include - -#include - -#include "rw_set.h" +#include #ifdef LOCAL_MAY #include @@ -203,7 +195,7 @@ void interrupt( // now instrument Forall_goto_functions(f_it, goto_model.goto_functions) - if(f_it->first!=CPROVER_PREFIX "initialize" && + if(f_it->first != INITIALIZE_FUNCTION && f_it->first!=goto_functionst::entry_point() && f_it->first!=isr.get_identifier()) interrupt( diff --git a/src/goto-instrument/mmio.cpp b/src/goto-instrument/mmio.cpp index e818e9c4ec8..db9df4293fe 100644 --- a/src/goto-instrument/mmio.cpp +++ b/src/goto-instrument/mmio.cpp @@ -13,7 +13,7 @@ Date: September 2011 #include "mmio.h" -#include +#include #include #include @@ -169,7 +169,7 @@ void mmio( // now instrument Forall_goto_functions(f_it, goto_model.goto_functions) - if(f_it->first!=CPROVER_PREFIX "initialize" && + if(f_it->first != INITIALIZE_FUNCTION && f_it->first!=goto_functionst::entry_point()) mmio(value_sets, goto_model.symbol_table, #ifdef LOCAL_MAY diff --git a/src/goto-instrument/nondet_static.cpp b/src/goto-instrument/nondet_static.cpp index 587b935f80a..2dce04f9d22 100644 --- a/src/goto-instrument/nondet_static.cpp +++ b/src/goto-instrument/nondet_static.cpp @@ -22,6 +22,8 @@ Date: November 2011 #include #include +#include + void nondet_static( const namespacet &ns, goto_functionst &goto_functions, @@ -75,7 +77,7 @@ void nondet_static( const namespacet &ns, goto_functionst &goto_functions) { - nondet_static(ns, goto_functions, CPROVER_PREFIX "initialize"); + nondet_static(ns, goto_functions, INITIALIZE_FUNCTION); // update counters etc. goto_functions.update(); diff --git a/src/goto-instrument/race_check.cpp b/src/goto-instrument/race_check.cpp index b426c98815e..8517e90f1ae 100644 --- a/src/goto-instrument/race_check.cpp +++ b/src/goto-instrument/race_check.cpp @@ -25,6 +25,8 @@ Date: February 2006 #include #include +#include + #include "rw_set.h" #ifdef LOCAL_MAY @@ -300,7 +302,7 @@ void race_check( Forall_goto_functions(f_it, goto_model.goto_functions) if(f_it->first!=goto_functionst::entry_point() && - f_it->first!=CPROVER_PREFIX "initialize") + f_it->first != INITIALIZE_FUNCTION) race_check( value_sets, goto_model.symbol_table, diff --git a/src/goto-instrument/stack_depth.cpp b/src/goto-instrument/stack_depth.cpp index 606a25f40bb..a0e0457fa24 100644 --- a/src/goto-instrument/stack_depth.cpp +++ b/src/goto-instrument/stack_depth.cpp @@ -22,6 +22,8 @@ Date: November 2011 #include +#include + symbol_exprt add_stack_depth_symbol(symbol_tablet &symbol_table) { const irep_idt identifier="$stack_depth"; @@ -94,17 +96,16 @@ void stack_depth( Forall_goto_functions(f_it, goto_model.goto_functions) if(f_it->second.body_available() && - f_it->first!=CPROVER_PREFIX "initialize" && + f_it->first != INITIALIZE_FUNCTION && f_it->first!=goto_functionst::entry_point()) stack_depth(f_it->second.body, sym, depth, depth_expr); // initialize depth to 0 - goto_functionst::function_mapt::iterator - i_it=goto_model.goto_functions.function_map.find( - CPROVER_PREFIX "initialize"); + goto_functionst::function_mapt::iterator i_it = + goto_model.goto_functions.function_map.find(INITIALIZE_FUNCTION); DATA_INVARIANT( i_it!=goto_model.goto_functions.function_map.end(), - "__CPROVER_initialize must exist"); + INITIALIZE_FUNCTION " must exist"); goto_programt &init=i_it->second.body; goto_programt::targett first=init.instructions.begin(); diff --git a/src/goto-instrument/wmm/goto2graph.cpp b/src/goto-instrument/wmm/goto2graph.cpp index 13587974058..9611f56d2f7 100644 --- a/src/goto-instrument/wmm/goto2graph.cpp +++ b/src/goto-instrument/wmm/goto2graph.cpp @@ -28,6 +28,8 @@ Date: 2012 #include #include +#include + #include "../rw_set.h" #include "fence.h" @@ -168,7 +170,7 @@ void instrumentert::cfg_visitort::visit_cfg_function( instrumenter.message.debug() << "visit function " << function << messaget::eom; - if(function==CPROVER_PREFIX "initialize") + if(function == INITIALIZE_FUNCTION) { return; } diff --git a/src/goto-instrument/wmm/shared_buffers.cpp b/src/goto-instrument/wmm/shared_buffers.cpp index bf78d1ac742..4f8a5e65247 100644 --- a/src/goto-instrument/wmm/shared_buffers.cpp +++ b/src/goto-instrument/wmm/shared_buffers.cpp @@ -7,6 +7,9 @@ Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ #include "shared_buffers.h" + +#include + #include "fence.h" #include "../rw_set.h" @@ -1054,7 +1057,7 @@ void shared_bufferst::cfg_visitort::weak_memory( { shared_buffers.message.debug() << "visit function "<< function << messaget::eom; - if(function==CPROVER_PREFIX "initialize") + if(function == INITIALIZE_FUNCTION) return; namespacet ns(symbol_table); diff --git a/src/goto-instrument/wmm/weak_memory.cpp b/src/goto-instrument/wmm/weak_memory.cpp index 468d944f14a..1f2e38b61da 100644 --- a/src/goto-instrument/wmm/weak_memory.cpp +++ b/src/goto-instrument/wmm/weak_memory.cpp @@ -29,6 +29,8 @@ Date: September 2011 #include +#include + #include "../rw_set.h" #include "shared_buffers.h" @@ -135,7 +137,7 @@ void weak_memory( // all access to shared variables is pushed into assignments Forall_goto_functions(f_it, goto_model.goto_functions) - if(f_it->first!=CPROVER_PREFIX "initialize" && + if(f_it->first != INITIALIZE_FUNCTION && f_it->first!=goto_functionst::entry_point()) introduce_temporaries(value_sets, goto_model.symbol_table, f_it->first, f_it->second.body, diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index 1597868caf2..ef4a4e70cc8 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -29,7 +29,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include "remove_exceptions.h" +#include + #include "java_object_factory.h" #include "java_types.h" #include "java_utils.h" diff --git a/src/jsil/jsil_entry_point.cpp b/src/jsil/jsil_entry_point.cpp index 991ca1c226c..a8f1278e961 100644 --- a/src/jsil/jsil_entry_point.cpp +++ b/src/jsil/jsil_entry_point.cpp @@ -20,13 +20,13 @@ Author: Michael Tautschnig, tautschn@amazon.com #include -#define INITIALIZE CPROVER_PREFIX "initialize" +#include static void create_initialize(symbol_tablet &symbol_table) { symbolt initialize; - initialize.name=CPROVER_PREFIX "initialize"; - initialize.base_name=CPROVER_PREFIX "initialize"; + initialize.name = INITIALIZE_FUNCTION; + initialize.base_name = INITIALIZE_FUNCTION; initialize.mode="jsil"; code_typet type; @@ -46,7 +46,7 @@ static void create_initialize(symbol_tablet &symbol_table) initialize.value=init_code; if(symbol_table.add(initialize)) - throw "failed to add " CPROVER_PREFIX "initialize"; + throw "failed to add " INITIALIZE_FUNCTION; } bool jsil_entry_point( @@ -130,10 +130,10 @@ bool jsil_entry_point( { symbol_tablet::symbolst::const_iterator init_it= - symbol_table.symbols.find(CPROVER_PREFIX "initialize"); + symbol_table.symbols.find(INITIALIZE_FUNCTION); if(init_it==symbol_table.symbols.end()) - throw "failed to find " CPROVER_PREFIX "initialize symbol"; + throw "failed to find " INITIALIZE_FUNCTION " symbol"; code_function_callt call_init; call_init.lhs().make_nil(); diff --git a/src/linking/remove_internal_symbols.cpp b/src/linking/remove_internal_symbols.cpp index 11037431b66..91f6e3c411d 100644 --- a/src/linking/remove_internal_symbols.cpp +++ b/src/linking/remove_internal_symbols.cpp @@ -18,6 +18,8 @@ Author: Daniel Kroening #include #include +#include "static_lifetime_init.h" + void get_symbols_rec( const namespacet &ns, const symbolt &symbol, @@ -84,7 +86,7 @@ void remove_internal_symbols( special.insert("envp'"); special.insert("envp_size'"); special.insert(CPROVER_PREFIX "memory"); - special.insert(CPROVER_PREFIX "initialize"); + special.insert(INITIALIZE_FUNCTION); special.insert(CPROVER_PREFIX "malloc_size"); special.insert(CPROVER_PREFIX "deallocated"); special.insert(CPROVER_PREFIX "dead_object"); From dfd6923af597c7628302287ccac7dfa50edbd254 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Thu, 26 Apr 2018 18:27:33 +0000 Subject: [PATCH 74/93] Use C++ streams instead of C-style snprintf --- src/ansi-c/expr2c.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/ansi-c/expr2c.cpp b/src/ansi-c/expr2c.cpp index 9a8a06ea799..f309f9be7ec 100644 --- a/src/ansi-c/expr2c.cpp +++ b/src/ansi-c/expr2c.cpp @@ -10,14 +10,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include -#include - -#ifdef _WIN32 -#ifndef __MINGW32__ -#define snprintf sprintf_s -#endif -#endif +#include #include #include @@ -2258,9 +2251,9 @@ std::string expr2ct::convert_array( dest+=static_cast(ch); else { - char hexbuf[10]; - snprintf(hexbuf, sizeof(hexbuf), "\\x%x", ch); - dest+=hexbuf; + std::ostringstream oss; + oss << "\\x" << std::hex << ch; + dest += oss.str(); last_was_hex=true; } } From 28cc66927e9f96e39dbae9396006342217a563cd Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Fri, 27 Apr 2018 08:34:28 +0100 Subject: [PATCH 75/93] Set mode of if_exprt introduced in preprocessing A temporary variable is introduced later for this if_exprt and the mode needs to be known for the variable, other an invariant may fail. --- src/java_bytecode/java_string_library_preprocess.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java_bytecode/java_string_library_preprocess.cpp b/src/java_bytecode/java_string_library_preprocess.cpp index 3c73c3e8ae6..655c696f659 100644 --- a/src/java_bytecode/java_string_library_preprocess.cpp +++ b/src/java_bytecode/java_string_library_preprocess.cpp @@ -902,10 +902,11 @@ void java_string_library_preprocesst::code_assign_java_string_to_string_expr( // Although we should not reach this code if rhs is null, the association // `pointer -> length` is added to the solver anyway, so we have to make sure // the length is set to something reasonable. - const auto rhs_length = if_exprt( + auto rhs_length = if_exprt( equal_exprt(rhs, null_pointer_exprt(to_pointer_type(rhs.type()))), from_integer(0, lhs.length().type()), get_length(deref, symbol_table)); + rhs_length.set(ID_mode, ID_java); // Assignments code.add(code_assignt(lhs.length(), rhs_length), loc); From a123ca92cf932dc917fc3f9f3c6838dbcc33a6a4 Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Fri, 27 Apr 2018 10:58:57 +0100 Subject: [PATCH 76/93] Add test where tmp_if_expr is introduced This checks the ID_mode fix for if_expr in preprocessing works correctly. --- .../jbmc-strings/char_escape/Test.class | Bin 0 -> 672 bytes regression/jbmc-strings/char_escape/Test.java | 19 ++++++++++++++++++ regression/jbmc-strings/char_escape/test.desc | 6 ++++++ 3 files changed, 25 insertions(+) create mode 100644 regression/jbmc-strings/char_escape/Test.class create mode 100644 regression/jbmc-strings/char_escape/Test.java create mode 100644 regression/jbmc-strings/char_escape/test.desc diff --git a/regression/jbmc-strings/char_escape/Test.class b/regression/jbmc-strings/char_escape/Test.class new file mode 100644 index 0000000000000000000000000000000000000000..5ffa97543e07f6203d0805cd7d65dc7b0f94a79c GIT binary patch literal 672 zcmZWmO>fgc6r6SZv2oq6(6n`%Kq-YdJ&+3$QiEElk>FC`kSK_Xi<7J(m*9ld>3@OW zkPDYq0;va%{3e8$wOtj_we;rg^Xz*wyTAT?zXtFOfeRO92kR0WE(~ny;Onp@vF)OQ zs)PFu9thYkqBu$p1qwmED`2+910}G062{CxoJ7I6cikYbML|`Fk<*R-wu-Hz* z{>RthBqed4fZHC=rhWA?(uay29(sBfUW6VN;0bK#yfF&nVWXW)qj-2ci$()A6@X^! zczB3i509`XAZ5|@7I$kO96a{$1T~7#{RCESyS(k4sXj~P;N-TLwQg!Zb~u@+cpy*- zTJ<}We0r0^l5uuQU@f>yB;%in)Oq9De@ikGQg{&MP3=IM?1(rGY<<0ghtis%!bCi*aIY^^P)fP&W=EK1bBx;n?psVNnb3{k4D6>Ou Zm!kWWt+2`uWEsEFbx>NOlY42~wZDqcerEsx literal 0 HcmV?d00001 diff --git a/regression/jbmc-strings/char_escape/Test.java b/regression/jbmc-strings/char_escape/Test.java new file mode 100644 index 00000000000..791563bbbc0 --- /dev/null +++ b/regression/jbmc-strings/char_escape/Test.java @@ -0,0 +1,19 @@ +public class Test { + + public static boolean test(char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8) { + StringBuilder sb = new StringBuilder(""); + sb.append(c1); + sb.append(c2); + sb.append(c3); + sb.append(c4); + sb.append(c5); + sb.append(c6); + sb.append(c7); + sb.append(c8); + if (sb.toString().equals("\b\t\n\f\r\"\'\\")) + return true; + if (!sb.toString().equals("\b\t\n\f\r\"\'\\")) + return false; + return true; + } +} diff --git a/regression/jbmc-strings/char_escape/test.desc b/regression/jbmc-strings/char_escape/test.desc new file mode 100644 index 00000000000..53ab05408c9 --- /dev/null +++ b/regression/jbmc-strings/char_escape/test.desc @@ -0,0 +1,6 @@ +CORE +Test.class +--refine-strings --function Test.test --cover location --trace --json-ui +^EXIT=0$ +^SIGNAL=0$ +20 of 23 covered \(87.0%\)|30 of 44 covered \(68.2%\) From 2408c229e8fa51fba0e879f497010179f5462176 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Thu, 26 Apr 2018 19:13:01 +0000 Subject: [PATCH 77/93] Do not unnecessarily use C string functions --- src/goto-programs/interpreter_evaluate.cpp | 9 +++------ src/goto-programs/string_abstraction.cpp | 10 ++++++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/goto-programs/interpreter_evaluate.cpp b/src/goto-programs/interpreter_evaluate.cpp index bb9ea793d0a..15db12bde80 100644 --- a/src/goto-programs/interpreter_evaluate.cpp +++ b/src/goto-programs/interpreter_evaluate.cpp @@ -389,14 +389,11 @@ void interpretert::evaluate( } else if(expr.type().id()==ID_string) { - irep_idt value=to_constant_expr(expr).get_value(); - const char *str=value.c_str(); - std::size_t length=strlen(str)+1; + const std::string &value = id2string(to_constant_expr(expr).get_value()); if(show) warning() << "string decoding not fully implemented " - << length << eom; - mp_integer tmp = get_string_container()[id2string(value)]; - dest.push_back(tmp); + << value.size() + 1 << eom; + dest.push_back(get_string_container()[value]); return; } else diff --git a/src/goto-programs/string_abstraction.cpp b/src/goto-programs/string_abstraction.cpp index bf97e4c0c5d..fd5a123c6df 100644 --- a/src/goto-programs/string_abstraction.cpp +++ b/src/goto-programs/string_abstraction.cpp @@ -11,8 +11,10 @@ Author: Daniel Kroening, kroening@kroening.com #include "string_abstraction.h" -#include +#include +#include +#include #include #include #include @@ -759,7 +761,11 @@ bool string_abstractiont::build(const exprt &object, exprt &dest, bool write) if(object.id()==ID_string_constant) { - mp_integer str_len=strlen(object.get(ID_value).c_str()); + const std::string &str_value = id2string(object.get(ID_value)); + // make sure we handle the case of a string constant with string-terminating + // \0 in it + const std::size_t str_len = + std::min(str_value.size(), str_value.find('\0')); return build_symbol_constant(str_len, str_len+1, dest); } From 063d3da7256399ceb2b8b6db3c55fba985bd8ffb Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Thu, 26 Apr 2018 18:30:28 +0000 Subject: [PATCH 78/93] Move asserts to invariants (and provide suitable includes) --- src/cpp/cpp_exception_id.cpp | 4 +++- src/cpp/cpp_name.h | 5 +++-- src/cpp/cpp_template_args.h | 9 +++++---- src/cpp/cpp_template_type.h | 5 +++-- src/cpp/cpp_token_buffer.h | 4 +++- src/cpp/template_map.cpp | 5 +++-- src/util/typecheck.cpp | 5 +++-- 7 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/cpp/cpp_exception_id.cpp b/src/cpp/cpp_exception_id.cpp index 23d7f49a30c..aef6606a4bd 100644 --- a/src/cpp/cpp_exception_id.cpp +++ b/src/cpp/cpp_exception_id.cpp @@ -11,6 +11,8 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include "cpp_exception_id.h" +#include + /// turns a type into a list of relevant exception IDs void cpp_exception_list_rec( const typet &src, @@ -91,6 +93,6 @@ irep_idt cpp_exception_id( { std::vector ids; cpp_exception_list_rec(src, ns, "", ids); - assert(!ids.empty()); + CHECK_RETURN(!ids.empty()); return ids.front(); } diff --git a/src/cpp/cpp_name.h b/src/cpp/cpp_name.h index a27374c5524..bb9e1007cf6 100644 --- a/src/cpp/cpp_name.h +++ b/src/cpp/cpp_name.h @@ -11,6 +11,7 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #define CPROVER_CPP_CPP_NAME_H #include +#include class cpp_namet:public irept { @@ -142,13 +143,13 @@ class cpp_namet:public irept inline cpp_namet &to_cpp_name(irept &cpp_name) { - assert(cpp_name.id() == ID_cpp_name); + PRECONDITION(cpp_name.id() == ID_cpp_name); return static_cast(cpp_name); } inline const cpp_namet &to_cpp_name(const irept &cpp_name) { - assert(cpp_name.id() == ID_cpp_name); + PRECONDITION(cpp_name.id() == ID_cpp_name); return static_cast(cpp_name); } diff --git a/src/cpp/cpp_template_args.h b/src/cpp/cpp_template_args.h index 47ceca5f003..22018dfaad4 100644 --- a/src/cpp/cpp_template_args.h +++ b/src/cpp/cpp_template_args.h @@ -13,6 +13,7 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #define CPROVER_CPP_CPP_TEMPLATE_ARGS_H #include +#include // A data structures for template arguments, i.e., // a sequence of types/expressions of the form . @@ -47,14 +48,14 @@ class cpp_template_args_non_tct:public cpp_template_args_baset inline cpp_template_args_non_tct &to_cpp_template_args_non_tc( irept &irep) { - assert(irep.id()==ID_template_args); + PRECONDITION(irep.id() == ID_template_args); return static_cast(irep); } inline const cpp_template_args_non_tct &to_cpp_template_args_non_tc( const irept &irep) { - assert(irep.id()==ID_template_args); + PRECONDITION(irep.id() == ID_template_args); return static_cast(irep); } @@ -80,13 +81,13 @@ class cpp_template_args_tct:public cpp_template_args_baset inline cpp_template_args_tct &to_cpp_template_args_tc(irept &irep) { - assert(irep.id()==ID_template_args); + PRECONDITION(irep.id() == ID_template_args); return static_cast(irep); } inline const cpp_template_args_tct &to_cpp_template_args_tc(const irept &irep) { - assert(irep.id()==ID_template_args); + PRECONDITION(irep.id() == ID_template_args); return static_cast(irep); } diff --git a/src/cpp/cpp_template_type.h b/src/cpp/cpp_template_type.h index 57e9d257e1d..de472b41a48 100644 --- a/src/cpp/cpp_template_type.h +++ b/src/cpp/cpp_template_type.h @@ -10,6 +10,7 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #ifndef CPROVER_CPP_CPP_TEMPLATE_TYPE_H #define CPROVER_CPP_CPP_TEMPLATE_TYPE_H +#include #include #include @@ -37,13 +38,13 @@ class template_typet:public typet inline template_typet &to_template_type(typet &type) { - assert(type.id()==ID_template); + PRECONDITION(type.id() == ID_template); return static_cast(type); } inline const template_typet &to_template_type(const typet &type) { - assert(type.id()==ID_template); + PRECONDITION(type.id() == ID_template); return static_cast(type); } diff --git a/src/cpp/cpp_token_buffer.h b/src/cpp/cpp_token_buffer.h index b24f84dbe70..4d3acdbfc3c 100644 --- a/src/cpp/cpp_token_buffer.h +++ b/src/cpp/cpp_token_buffer.h @@ -16,6 +16,8 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include +#include + class cpp_token_buffert { public: @@ -45,7 +47,7 @@ class cpp_token_buffert // the token that is currently being read from the file cpp_tokent ¤t_token() { - assert(!tokens.empty()); + PRECONDITION(!tokens.empty()); return tokens.back(); } diff --git a/src/cpp/template_map.cpp b/src/cpp/template_map.cpp index 16949d7aaa7..3526603d1dc 100644 --- a/src/cpp/template_map.cpp +++ b/src/cpp/template_map.cpp @@ -173,14 +173,15 @@ void template_mapt::build( } // these should have been typechecked before - assert(instance.size()==template_parameters.size()); + DATA_INVARIANT( + instance.size() == template_parameters.size(), + "template instantiation expected to match declaration"); for(cpp_template_args_tct::argumentst::const_iterator i_it=instance.begin(); i_it!=instance.end(); i_it++, t_it++) { - assert(t_it!=template_parameters.end()); set(*t_it, *i_it); } } diff --git a/src/util/typecheck.cpp b/src/util/typecheck.cpp index a09f54d8ff0..24c57c8a7b7 100644 --- a/src/util/typecheck.cpp +++ b/src/util/typecheck.cpp @@ -6,12 +6,13 @@ Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ - #include "typecheck.h" +#include "invariant.h" + bool typecheckt::typecheck_main() { - assert(message_handler); + PRECONDITION(message_handler); const unsigned errors_before= message_handler->get_message_count(messaget::M_ERROR); From 87d0dbb6a05f9b2672bfdbeae8ac843b01d5e4fd Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Thu, 26 Apr 2018 19:15:35 +0000 Subject: [PATCH 79/93] Use pointer_offset_bits instead of locally hacking up what it does anyway --- src/goto-programs/vcd_goto_trace.cpp | 19 ++----------------- .../value_set_dereference.cpp | 18 ++---------------- 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/src/goto-programs/vcd_goto_trace.cpp b/src/goto-programs/vcd_goto_trace.cpp index 4becb3af583..7acc15e890b 100644 --- a/src/goto-programs/vcd_goto_trace.cpp +++ b/src/goto-programs/vcd_goto_trace.cpp @@ -63,17 +63,7 @@ std::string as_vcd_binary( // build "xxx" - mp_integer width; - - if(type.id()==ID_unsignedbv || - type.id()==ID_signedbv || - type.id()==ID_floatbv || - type.id()==ID_fixedbv || - type.id()==ID_pointer || - type.id()==ID_bv) - width=string2integer(type.get_string(ID_width)); - else - width=pointer_offset_size(type, ns)*8; + const mp_integer width = pointer_offset_bits(type, ns); if(width>=0) return std::string(integer2size_t(width), 'x'); @@ -106,12 +96,7 @@ void output_vcd( const auto number=n.number(identifier); - mp_integer width; - - if(type.id()==ID_bool) - width=1; - else - width=pointer_offset_bits(type, ns); + const mp_integer width = pointer_offset_bits(type, ns); if(width>=1) out << "$var reg " << width << " V" << number << " " diff --git a/src/pointer-analysis/value_set_dereference.cpp b/src/pointer-analysis/value_set_dereference.cpp index 59a62f31cd6..4e437ede5ea 100644 --- a/src/pointer-analysis/value_set_dereference.cpp +++ b/src/pointer-analysis/value_set_dereference.cpp @@ -712,20 +712,6 @@ void value_set_dereferencet::bounds_check( } } -inline static unsigned bv_width( - const typet &type, - const namespacet &ns) -{ - if(type.id()==ID_c_enum_tag) - { - const typet &t=ns.follow_tag(to_c_enum_tag_type(type)); - assert(t.id()==ID_c_enum); - return bv_width(t.subtype(), ns); - } - - return unsafe_string2unsigned(type.get_string(ID_width)); -} - static bool is_a_bv_type(const typet &type) { return type.id()==ID_unsignedbv || @@ -752,7 +738,7 @@ bool value_set_dereferencet::memory_model( if(is_a_bv_type(from_type) && is_a_bv_type(to_type)) { - if(bv_width(from_type, ns)==bv_width(to_type, ns)) + if(pointer_offset_bits(from_type, ns) == pointer_offset_bits(to_type, ns)) { // avoid semantic conversion in case of // cast to float or fixed-point, @@ -772,7 +758,7 @@ bool value_set_dereferencet::memory_model( if(from_type.id()==ID_pointer && to_type.id()==ID_pointer) { - if(bv_width(from_type, ns)==bv_width(to_type, ns)) + if(pointer_offset_bits(from_type, ns) == pointer_offset_bits(to_type, ns)) return memory_model_conversion(value, to_type, guard, offset); } From 5b29e22bf842281ad70243d744739fa1ff28c922 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Thu, 26 Apr 2018 19:18:53 +0000 Subject: [PATCH 80/93] Move definition of base_type_eqt to .cpp This is an implementation detail that need not be exposed to users - the interface is the free function base_type_eq. --- src/util/base_type.cpp | 33 +++++++++++++++++++++++++++++++++ src/util/base_type.h | 35 ----------------------------------- 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/util/base_type.cpp b/src/util/base_type.cpp index 62d40ad32e5..4aba15b5505 100644 --- a/src/util/base_type.cpp +++ b/src/util/base_type.cpp @@ -17,6 +17,39 @@ Author: Daniel Kroening, kroening@kroening.com #include "std_types.h" #include "namespace.h" #include "symbol.h" +#include "union_find.h" + +class base_type_eqt +{ +public: + explicit base_type_eqt(const namespacet &_ns):ns(_ns) + { + } + + bool base_type_eq(const typet &type1, const typet &type2) + { + identifiers.clear(); + return base_type_eq_rec(type1, type2); + } + + bool base_type_eq(const exprt &expr1, const exprt &expr2) + { + identifiers.clear(); + return base_type_eq_rec(expr1, expr2); + } + + virtual ~base_type_eqt() { } + +protected: + const namespacet &ns; + + virtual bool base_type_eq_rec(const typet &type1, const typet &type2); + virtual bool base_type_eq_rec(const exprt &expr1, const exprt &expr2); + + // for loop avoidance + typedef union_find identifierst; + identifierst identifiers; +}; void base_type_rec( typet &type, const namespacet &ns, std::set &symb) diff --git a/src/util/base_type.h b/src/util/base_type.h index 833fd855cca..6315ac09542 100644 --- a/src/util/base_type.h +++ b/src/util/base_type.h @@ -12,9 +12,6 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_UTIL_BASE_TYPE_H #define CPROVER_UTIL_BASE_TYPE_H -#include "union_find.h" -#include "irep.h" - class exprt; class typet; class namespacet; @@ -29,36 +26,4 @@ bool base_type_eq( const exprt &expr2, const namespacet &ns); -class base_type_eqt -{ -public: - explicit base_type_eqt(const namespacet &_ns):ns(_ns) - { - } - - bool base_type_eq(const typet &type1, const typet &type2) - { - identifiers.clear(); - return base_type_eq_rec(type1, type2); - } - - bool base_type_eq(const exprt &expr1, const exprt &expr2) - { - identifiers.clear(); - return base_type_eq_rec(expr1, expr2); - } - - virtual ~base_type_eqt() { } - -protected: - const namespacet &ns; - - virtual bool base_type_eq_rec(const typet &type1, const typet &type2); - virtual bool base_type_eq_rec(const exprt &expr1, const exprt &expr2); - - // for loop avoidance - typedef union_find identifierst; - identifierst identifiers; -}; - #endif // CPROVER_UTIL_BASE_TYPE_H From 49cfaf7ceda670e81bc5d08993125df5f512c2a7 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Thu, 26 Apr 2018 18:26:42 +0000 Subject: [PATCH 81/93] Remove unused includes ... and sort the remaining ones lexicographically. --- src/analyses/goto_rw.h | 2 +- src/ansi-c/ansi_c_entry_point.cpp | 9 ------ src/ansi-c/c_nondet_symbol_factory.cpp | 8 ------ src/ansi-c/c_typecheck_expr.cpp | 11 +++----- src/ansi-c/c_typecheck_type.cpp | 9 ++---- src/ansi-c/expr2c.cpp | 13 +++------ src/ansi-c/type2name.cpp | 7 ++--- src/cbmc/bmc.cpp | 19 ++----------- src/cbmc/symex_coverage.cpp | 9 ++---- src/cbmc/symex_coverage.h | 2 +- src/cpp/cpp_template_type.h | 1 - src/cpp/cpp_typecheck_expr.cpp | 13 +++------ src/cpp/cpp_typecheck_initializer.cpp | 3 -- src/goto-analyzer/static_show_domain.cpp | 2 ++ src/goto-analyzer/static_show_domain.h | 10 +++---- src/goto-analyzer/static_simplifier.cpp | 14 +++++----- src/goto-analyzer/static_simplifier.h | 10 +++---- src/goto-analyzer/static_verifier.cpp | 9 ++++-- src/goto-analyzer/static_verifier.h | 10 +++---- .../unreachable_instructions.cpp | 12 ++++---- src/goto-analyzer/unreachable_instructions.h | 10 +++---- src/goto-cc/compile.cpp | 14 +++------- src/goto-cc/linker_script_merge.cpp | 15 +++------- src/goto-diff/goto_diff.h | 9 +++--- src/goto-diff/goto_diff_base.cpp | 5 ++-- src/goto-diff/syntactic_diff.cpp | 2 ++ src/goto-instrument/alignment_checks.cpp | 3 +- src/goto-instrument/call_sequences.cpp | 2 -- src/goto-instrument/code_contracts.cpp | 1 - src/goto-instrument/dump_c.cpp | 12 ++------ src/goto-instrument/mmio.cpp | 12 -------- src/goto-instrument/nondet_static.cpp | 6 ---- src/goto-instrument/object_id.h | 2 +- src/goto-instrument/race_check.cpp | 10 ------- src/goto-instrument/rw_set.h | 6 ++-- src/goto-instrument/stack_depth.cpp | 5 ---- src/goto-instrument/wmm/goto2graph.cpp | 9 ------ src/goto-instrument/wmm/shared_buffers.cpp | 6 ++-- src/goto-instrument/wmm/weak_memory.cpp | 4 --- src/goto-programs/builtin_functions.cpp | 9 ------ src/goto-programs/class_hierarchy.h | 4 ++- .../generate_function_bodies.cpp | 9 +----- src/goto-programs/goto_functions.h | 10 +++---- src/goto-programs/goto_program.h | 1 - src/goto-programs/interpreter_evaluate.cpp | 10 ++----- src/goto-programs/remove_asm.cpp | 5 ++-- src/goto-programs/remove_asm.h | 5 +++- src/goto-programs/remove_calls_no_body.cpp | 5 +++- src/goto-programs/remove_calls_no_body.h | 4 ++- src/goto-programs/remove_complex.cpp | 4 +++ src/goto-programs/remove_complex.h | 4 ++- .../remove_const_function_pointers.cpp | 9 ++++-- .../remove_const_function_pointers.h | 17 ++++++++--- src/goto-programs/remove_function_pointers.h | 7 +++-- src/goto-programs/remove_returns.cpp | 3 +- src/goto-programs/remove_returns.h | 9 +++++- src/goto-programs/remove_skip.h | 3 +- src/goto-programs/remove_unreachable.cpp | 2 ++ src/goto-programs/remove_unreachable.h | 3 +- src/goto-programs/remove_unused_functions.cpp | 2 ++ src/goto-programs/remove_unused_functions.h | 9 ++++-- src/goto-programs/remove_vector.cpp | 4 +++ src/goto-programs/remove_vector.h | 4 ++- .../remove_virtual_functions.cpp | 12 ++++---- src/goto-programs/remove_virtual_functions.h | 9 +++++- src/goto-programs/string_abstraction.cpp | 6 ---- src/goto-programs/vcd_goto_trace.cpp | 6 ++-- .../equation_conversion_exceptions.h | 2 +- src/goto-symex/goto_symex.h | 2 +- src/goto-symex/symex_builtin_functions.cpp | 14 ++-------- src/goto-symex/symex_clean_expr.cpp | 5 ++-- src/goto-symex/symex_dereference.cpp | 8 ++---- src/goto-symex/symex_function_call.cpp | 12 ++------ src/goto-symex/symex_other.cpp | 6 +--- src/java_bytecode/java_entry_point.cpp | 20 ++----------- src/java_bytecode/java_object_factory.cpp | 20 +------------ src/jsil/jsil_entry_point.cpp | 3 -- src/linking/linking.cpp | 10 +++---- src/linking/remove_internal_symbols.cpp | 7 ++--- src/linking/static_lifetime_init.h | 7 +++-- src/linking/zero_initializer.cpp | 11 +++----- src/pointer-analysis/value_set.cpp | 12 ++------ .../value_set_dereference.cpp | 24 ++++------------ src/solvers/flattening/boolbv_update.cpp | 6 ---- src/solvers/flattening/bv_pointers.cpp | 6 +--- .../flattening/flatten_byte_operators.cpp | 10 +++---- src/solvers/flattening/pointer_logic.cpp | 5 ++-- src/util/base_type.cpp | 3 +- src/util/fresh_symbol.cpp | 2 ++ src/util/fresh_symbol.h | 10 ++++--- src/util/graph.h | 12 ++++---- src/util/invariant_utils.h | 3 +- src/util/irep.h | 2 -- src/util/irep_hash_container.h | 13 ++++----- src/util/json_irep.h | 2 +- src/util/json_stream.h | 2 +- src/util/nondet_bool.h | 4 +-- src/util/nondet_ifthenelse.h | 2 +- src/util/numbering.h | 5 ++-- src/util/pointer_offset_size.cpp | 10 ++----- src/util/pointer_predicates.cpp | 6 ++-- src/util/rational.h | 3 -- src/util/refined_string_type.cpp | 2 ++ src/util/refined_string_type.h | 7 ++--- src/util/sharing_map.h | 8 ++---- src/util/sharing_node.h | 1 - src/util/simplify_expr.cpp | 28 ++++++++----------- src/util/simplify_expr_array.cpp | 9 ++---- src/util/simplify_expr_int.cpp | 2 -- src/util/simplify_expr_pointer.cpp | 12 ++++---- src/util/simplify_expr_struct.cpp | 9 ++---- src/util/ssa_expr.h | 2 +- src/util/std_expr.cpp | 2 -- src/util/string_expr.h | 6 ++-- src/util/symbol_table_base.h | 4 --- src/util/union_find_replace.h | 2 +- 116 files changed, 308 insertions(+), 536 deletions(-) diff --git a/src/analyses/goto_rw.h b/src/analyses/goto_rw.h index bc1c848413f..d84c6da1964 100644 --- a/src/analyses/goto_rw.h +++ b/src/analyses/goto_rw.h @@ -12,9 +12,9 @@ Date: April 2010 #ifndef CPROVER_ANALYSES_GOTO_RW_H #define CPROVER_ANALYSES_GOTO_RW_H -#include #include #include +#include #include // unique_ptr #include diff --git a/src/ansi-c/ansi_c_entry_point.cpp b/src/ansi-c/ansi_c_entry_point.cpp index 04da6131608..f15a3124f55 100644 --- a/src/ansi-c/ansi_c_entry_point.cpp +++ b/src/ansi-c/ansi_c_entry_point.cpp @@ -8,19 +8,10 @@ Author: Daniel Kroening, kroening@kroening.com #include "ansi_c_entry_point.h" -#include -#include - #include #include #include -#include -#include -#include -#include -#include #include -#include #include diff --git a/src/ansi-c/c_nondet_symbol_factory.cpp b/src/ansi-c/c_nondet_symbol_factory.cpp index 9b7d88d2bfb..8200e70a84e 100644 --- a/src/ansi-c/c_nondet_symbol_factory.cpp +++ b/src/ansi-c/c_nondet_symbol_factory.cpp @@ -11,22 +11,14 @@ Author: Diffblue Ltd. #include "c_nondet_symbol_factory.h" -#include -#include - #include #include #include #include -#include -#include -#include #include #include #include -#include - #include /// Create a new temporary static symbol diff --git a/src/ansi-c/c_typecheck_expr.cpp b/src/ansi-c/c_typecheck_expr.cpp index 5a8eb6cfb4e..b3d7389f995 100644 --- a/src/ansi-c/c_typecheck_expr.cpp +++ b/src/ansi-c/c_typecheck_expr.cpp @@ -14,17 +14,14 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include -#include -#include -#include #include -#include -#include -#include -#include +#include #include #include +#include +#include #include "builtin_factory.h" #include "c_typecast.h" diff --git a/src/ansi-c/c_typecheck_type.cpp b/src/ansi-c/c_typecheck_type.cpp index 1acc58d2f20..dcb40a0e897 100644 --- a/src/ansi-c/c_typecheck_type.cpp +++ b/src/ansi-c/c_typecheck_type.cpp @@ -13,19 +13,16 @@ Author: Daniel Kroening, kroening@kroening.com #include +#include #include #include -#include -#include -#include -#include #include +#include +#include "ansi_c_convert_type.h" #include "c_qualifiers.h" -#include "ansi_c_declaration.h" #include "padding.h" #include "type2name.h" -#include "ansi_c_convert_type.h" void c_typecheck_baset::typecheck_type(typet &type) { diff --git a/src/ansi-c/expr2c.cpp b/src/ansi-c/expr2c.cpp index f309f9be7ec..305a38e008f 100644 --- a/src/ansi-c/expr2c.cpp +++ b/src/ansi-c/expr2c.cpp @@ -13,23 +13,18 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include #include #include #include -#include -#include -#include +#include #include -#include -#include #include +#include #include -#include -#include -#include #include +#include +#include #include "c_misc.h" #include "c_qualifiers.h" diff --git a/src/ansi-c/type2name.cpp b/src/ansi-c/type2name.cpp index 3f1b6e85905..614b46b7ea0 100644 --- a/src/ansi-c/type2name.cpp +++ b/src/ansi-c/type2name.cpp @@ -11,13 +11,12 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include "type2name.h" -#include #include +#include #include -#include -#include #include -#include +#include +#include typedef std::unordered_map> symbol_numbert; diff --git a/src/cbmc/bmc.cpp b/src/cbmc/bmc.cpp index e0af60274f5..545ab8a54f1 100644 --- a/src/cbmc/bmc.cpp +++ b/src/cbmc/bmc.cpp @@ -12,35 +12,22 @@ Author: Daniel Kroening, kroening@kroening.com #include "bmc.h" #include -#include -#include #include -#include #include #include -#include #include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include +#include +#include #include +#include #include #include -#include -#include -#include #include diff --git a/src/cbmc/symex_coverage.cpp b/src/cbmc/symex_coverage.cpp index 77f7fe93ba6..0ecd58b1083 100644 --- a/src/cbmc/symex_coverage.cpp +++ b/src/cbmc/symex_coverage.cpp @@ -13,16 +13,13 @@ Date: March 2016 #include "symex_coverage.h" -#include #include -#include +#include #include -#include +#include -#include #include -#include -#include +#include #include diff --git a/src/cbmc/symex_coverage.h b/src/cbmc/symex_coverage.h index 9bba52fd84b..6eac2cf4ef7 100644 --- a/src/cbmc/symex_coverage.h +++ b/src/cbmc/symex_coverage.h @@ -14,9 +14,9 @@ Date: March 2016 #ifndef CPROVER_CBMC_SYMEX_COVERAGE_H #define CPROVER_CBMC_SYMEX_COVERAGE_H -#include #include #include +#include #include diff --git a/src/cpp/cpp_template_type.h b/src/cpp/cpp_template_type.h index de472b41a48..9c69e6208de 100644 --- a/src/cpp/cpp_template_type.h +++ b/src/cpp/cpp_template_type.h @@ -12,7 +12,6 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include #include -#include #include "cpp_template_parameter.h" diff --git a/src/cpp/cpp_typecheck_expr.cpp b/src/cpp/cpp_typecheck_expr.cpp index a6502391c3e..45d7c872759 100644 --- a/src/cpp/cpp_typecheck_expr.cpp +++ b/src/cpp/cpp_typecheck_expr.cpp @@ -15,23 +15,18 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include #endif -#include -#include #include -#include -#include -#include #include -#include - #include +#include +#include + #include #include -#include "cpp_type2name.h" -#include "cpp_convert_type.h" #include "cpp_exception_id.h" +#include "cpp_type2name.h" #include "expr2cpp.h" bool cpp_typecheckt::find_parent( diff --git a/src/cpp/cpp_typecheck_initializer.cpp b/src/cpp/cpp_typecheck_initializer.cpp index 565bca8a4bb..c4c85637878 100644 --- a/src/cpp/cpp_typecheck_initializer.cpp +++ b/src/cpp/cpp_typecheck_initializer.cpp @@ -14,12 +14,9 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include #include #include -#include #include -#include "cpp_util.h" - /// Initialize an object with a value void cpp_typecheckt::convert_initializer(symbolt &symbol) { diff --git a/src/goto-analyzer/static_show_domain.cpp b/src/goto-analyzer/static_show_domain.cpp index 99c8d63cefd..835311faf09 100644 --- a/src/goto-analyzer/static_show_domain.cpp +++ b/src/goto-analyzer/static_show_domain.cpp @@ -8,6 +8,8 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk #include "static_show_domain.h" +#include + #include /// Runs the analyzer and then prints out the domain diff --git a/src/goto-analyzer/static_show_domain.h b/src/goto-analyzer/static_show_domain.h index 1b2c3ee3772..71a6e90ef92 100644 --- a/src/goto-analyzer/static_show_domain.h +++ b/src/goto-analyzer/static_show_domain.h @@ -11,12 +11,10 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk #include -#include -#include - -#include - -#include +class ai_baset; +class goto_modelt; +class message_handlert; +class optionst; bool static_show_domain( const goto_modelt &, diff --git a/src/goto-analyzer/static_simplifier.cpp b/src/goto-analyzer/static_simplifier.cpp index 9e6ffa57822..08e29037c70 100644 --- a/src/goto-analyzer/static_simplifier.cpp +++ b/src/goto-analyzer/static_simplifier.cpp @@ -6,17 +6,17 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk \*******************************************************************/ +#include "static_simplifier.h" + +#include +#include + +#include #include #include #include -#include -#include -#include -#include - -#include "static_simplifier.h" - +#include /// Simplifies the program using the information in the abstract domain. /// \param goto_model: the program analyzed diff --git a/src/goto-analyzer/static_simplifier.h b/src/goto-analyzer/static_simplifier.h index 59e741fba83..557d94737c0 100644 --- a/src/goto-analyzer/static_simplifier.h +++ b/src/goto-analyzer/static_simplifier.h @@ -11,12 +11,10 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk #include -#include -#include - -#include - -#include +class ai_baset; +class goto_modelt; +class message_handlert; +class optionst; bool static_simplifier( goto_modelt &, diff --git a/src/goto-analyzer/static_verifier.cpp b/src/goto-analyzer/static_verifier.cpp index 660d20bd37e..f4fbc6320b7 100644 --- a/src/goto-analyzer/static_verifier.cpp +++ b/src/goto-analyzer/static_verifier.cpp @@ -8,11 +8,14 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk #include "static_verifier.h" -#include -#include -#include #include +#include +#include +#include +#include + +#include /// Runs the analyzer and then prints out the domain /// \param goto_model: the program analyzed diff --git a/src/goto-analyzer/static_verifier.h b/src/goto-analyzer/static_verifier.h index e71bdfbb45c..87358a30958 100644 --- a/src/goto-analyzer/static_verifier.h +++ b/src/goto-analyzer/static_verifier.h @@ -11,12 +11,10 @@ Author: Martin Brain, martin.brain@cs.ox.ac.uk #include -#include -#include - -#include - -#include +class ai_baset; +class goto_modelt; +class message_handlert; +class optionst; bool static_verifier( const goto_modelt &, diff --git a/src/goto-analyzer/unreachable_instructions.cpp b/src/goto-analyzer/unreachable_instructions.cpp index 0e783baaba5..c691142aead 100644 --- a/src/goto-analyzer/unreachable_instructions.cpp +++ b/src/goto-analyzer/unreachable_instructions.cpp @@ -13,18 +13,16 @@ Date: April 2016 #include "unreachable_instructions.h" -#include - -#include -#include #include +#include +#include #include -#include - -#include #include +#include +#include + typedef std::map dead_mapt; static void unreachable_instructions( diff --git a/src/goto-analyzer/unreachable_instructions.h b/src/goto-analyzer/unreachable_instructions.h index edffd0f7b1c..eeee658ea52 100644 --- a/src/goto-analyzer/unreachable_instructions.h +++ b/src/goto-analyzer/unreachable_instructions.h @@ -14,14 +14,12 @@ Date: April 2016 #ifndef CPROVER_GOTO_ANALYZER_UNREACHABLE_INSTRUCTIONS_H #define CPROVER_GOTO_ANALYZER_UNREACHABLE_INSTRUCTIONS_H -#include - -#include - -#include -#include +#include +class ai_baset; class goto_modelt; +class message_handlert; +class optionst; void unreachable_instructions( const goto_modelt &, diff --git a/src/goto-cc/compile.cpp b/src/goto-cc/compile.cpp index c092f940f95..98550ce7375 100644 --- a/src/goto-cc/compile.cpp +++ b/src/goto-cc/compile.cpp @@ -15,27 +15,21 @@ Date: June 2006 #include #include -#include #include -#include -#include -#include -#include -#include #include +#include #include -#include -#include -#include #include +#include +#include +#include #include #include #include #include -#include #include #include diff --git a/src/goto-cc/linker_script_merge.cpp b/src/goto-cc/linker_script_merge.cpp index c7ede967768..d89900d11f3 100644 --- a/src/goto-cc/linker_script_merge.cpp +++ b/src/goto-cc/linker_script_merge.cpp @@ -6,32 +6,25 @@ Author: Kareem Khazem , 2017 \*******************************************************************/ -#include +#include "linker_script_merge.h" #include -#include -#include -#include #include +#include #include #include -#include -#include #include -#include #include -#include #include +#include + #include #include #include -#include "compile.h" -#include "linker_script_merge.h" - int linker_script_merget::add_linker_script_definitions() { if(!cmdline.isset('T') || elf_binaries.size()!=1) diff --git a/src/goto-diff/goto_diff.h b/src/goto-diff/goto_diff.h index 72171a76b31..efb90d1ed1d 100644 --- a/src/goto-diff/goto_diff.h +++ b/src/goto-diff/goto_diff.h @@ -12,13 +12,14 @@ Author: Peter Schrammel #ifndef CPROVER_GOTO_DIFF_GOTO_DIFF_H #define CPROVER_GOTO_DIFF_GOTO_DIFF_H -#include - -#include #include -#include +#include +#include +class goto_modelt; +class json_arrayt; +class json_objectt; class optionst; class goto_difft:public messaget diff --git a/src/goto-diff/goto_diff_base.cpp b/src/goto-diff/goto_diff_base.cpp index db3b925d702..a06b13edf2b 100644 --- a/src/goto-diff/goto_diff_base.cpp +++ b/src/goto-diff/goto_diff_base.cpp @@ -11,11 +11,12 @@ Author: Peter Schrammel #include "goto_diff.h" -#include - #include #include +#include +#include + /// Output diff result void goto_difft::output_functions() const { diff --git a/src/goto-diff/syntactic_diff.cpp b/src/goto-diff/syntactic_diff.cpp index 83f4ef04a78..558bf1a8eb8 100644 --- a/src/goto-diff/syntactic_diff.cpp +++ b/src/goto-diff/syntactic_diff.cpp @@ -11,6 +11,8 @@ Author: Peter Schrammel #include "syntactic_diff.h" +#include + bool syntactic_difft::operator()() { forall_goto_functions(it, goto_model1.goto_functions) diff --git a/src/goto-instrument/alignment_checks.cpp b/src/goto-instrument/alignment_checks.cpp index 68c173bda7a..758539c68be 100644 --- a/src/goto-instrument/alignment_checks.cpp +++ b/src/goto-instrument/alignment_checks.cpp @@ -11,9 +11,8 @@ Module: Alignment Checks #include "alignment_checks.h" -#include #include -#include +#include void print_struct_alignment_problems( const symbol_tablet &symbol_table, diff --git a/src/goto-instrument/call_sequences.cpp b/src/goto-instrument/call_sequences.cpp index 82da31087b8..ca36d43ee99 100644 --- a/src/goto-instrument/call_sequences.cpp +++ b/src/goto-instrument/call_sequences.cpp @@ -15,9 +15,7 @@ Date: April 2013 #include #include -#include -#include #include #include diff --git a/src/goto-instrument/code_contracts.cpp b/src/goto-instrument/code_contracts.cpp index 16f3ebe8312..98d0d1248eb 100644 --- a/src/goto-instrument/code_contracts.cpp +++ b/src/goto-instrument/code_contracts.cpp @@ -13,7 +13,6 @@ Date: February 2016 #include "code_contracts.h" -#include #include #include diff --git a/src/goto-instrument/dump_c.cpp b/src/goto-instrument/dump_c.cpp index c51a6859d3e..2715f303063 100644 --- a/src/goto-instrument/dump_c.cpp +++ b/src/goto-instrument/dump_c.cpp @@ -11,16 +11,10 @@ Author: Daniel Kroening, kroening@kroening.com #include "dump_c.h" -#include -#include - +#include #include -#include -#include -#include #include -#include -#include +#include #include #include @@ -28,8 +22,8 @@ Author: Daniel Kroening, kroening@kroening.com #include -#include "goto_program2code.h" #include "dump_c_class.h" +#include "goto_program2code.h" inline std::ostream &operator << (std::ostream &out, dump_ct &src) { diff --git a/src/goto-instrument/mmio.cpp b/src/goto-instrument/mmio.cpp index db9df4293fe..0e0a2a03693 100644 --- a/src/goto-instrument/mmio.cpp +++ b/src/goto-instrument/mmio.cpp @@ -15,18 +15,6 @@ Date: September 2011 #include -#include -#include - -#if 0 -#include -#include -#include - -#include -#endif - -#include "interrupt.h" #include "rw_set.h" #ifdef LOCAL_MAY diff --git a/src/goto-instrument/nondet_static.cpp b/src/goto-instrument/nondet_static.cpp index 2dce04f9d22..51cbf5034fe 100644 --- a/src/goto-instrument/nondet_static.cpp +++ b/src/goto-instrument/nondet_static.cpp @@ -14,13 +14,7 @@ Date: November 2011 #include "nondet_static.h" -#include -#include -#include -#include - #include -#include #include diff --git a/src/goto-instrument/object_id.h b/src/goto-instrument/object_id.h index 98e4b03033b..509bf6a15c5 100644 --- a/src/goto-instrument/object_id.h +++ b/src/goto-instrument/object_id.h @@ -12,8 +12,8 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_GOTO_INSTRUMENT_OBJECT_ID_H #define CPROVER_GOTO_INSTRUMENT_OBJECT_ID_H -#include #include +#include #include #include diff --git a/src/goto-instrument/race_check.cpp b/src/goto-instrument/race_check.cpp index 8517e90f1ae..0289148f1ec 100644 --- a/src/goto-instrument/race_check.cpp +++ b/src/goto-instrument/race_check.cpp @@ -13,16 +13,6 @@ Date: February 2006 #include "race_check.h" -#include -#include -#include -#include -#include - -#include -#include - -#include #include #include diff --git a/src/goto-instrument/rw_set.h b/src/goto-instrument/rw_set.h index 69072389347..3dd99a9a7db 100644 --- a/src/goto-instrument/rw_set.h +++ b/src/goto-instrument/rw_set.h @@ -19,17 +19,17 @@ Date: February 2006 #include #include -#include -#include #include #include -#include #ifdef LOCAL_MAY #include #endif +class namespacet; +class value_setst; + // a container for read/write sets class rw_set_baset diff --git a/src/goto-instrument/stack_depth.cpp b/src/goto-instrument/stack_depth.cpp index a0e0457fa24..9784d648f39 100644 --- a/src/goto-instrument/stack_depth.cpp +++ b/src/goto-instrument/stack_depth.cpp @@ -13,12 +13,7 @@ Date: November 2011 #include "stack_depth.h" -#include -#include -#include -#include #include -#include #include diff --git a/src/goto-instrument/wmm/goto2graph.cpp b/src/goto-instrument/wmm/goto2graph.cpp index 9611f56d2f7..6d130be954b 100644 --- a/src/goto-instrument/wmm/goto2graph.cpp +++ b/src/goto-instrument/wmm/goto2graph.cpp @@ -16,17 +16,8 @@ Date: 2012 #include #include #include -#include -#ifndef _WIN32 -#include -#endif - -#include -#include #include -#include -#include #include diff --git a/src/goto-instrument/wmm/shared_buffers.cpp b/src/goto-instrument/wmm/shared_buffers.cpp index 4f8a5e65247..feadf6af1ad 100644 --- a/src/goto-instrument/wmm/shared_buffers.cpp +++ b/src/goto-instrument/wmm/shared_buffers.cpp @@ -8,12 +8,12 @@ Author: Daniel Kroening, kroening@kroening.com #include "shared_buffers.h" +#include + #include -#include "fence.h" #include "../rw_set.h" - -#include +#include "fence.h" /// returns a unique id (for fresh variables) std::string shared_bufferst::unique(void) diff --git a/src/goto-instrument/wmm/weak_memory.cpp b/src/goto-instrument/wmm/weak_memory.cpp index 1f2e38b61da..155e2064383 100644 --- a/src/goto-instrument/wmm/weak_memory.cpp +++ b/src/goto-instrument/wmm/weak_memory.cpp @@ -23,10 +23,6 @@ Date: September 2011 #include -#include -#include -#include - #include #include diff --git a/src/goto-programs/builtin_functions.cpp b/src/goto-programs/builtin_functions.cpp index ba1dfb7c685..13685785d71 100644 --- a/src/goto-programs/builtin_functions.cpp +++ b/src/goto-programs/builtin_functions.cpp @@ -17,17 +17,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include #include diff --git a/src/goto-programs/class_hierarchy.h b/src/goto-programs/class_hierarchy.h index 9b926d25e18..1d180369765 100644 --- a/src/goto-programs/class_hierarchy.h +++ b/src/goto-programs/class_hierarchy.h @@ -19,7 +19,9 @@ Date: April 2016 #include #include -#include +#include + +class symbol_tablet; class class_hierarchyt { diff --git a/src/goto-programs/generate_function_bodies.cpp b/src/goto-programs/generate_function_bodies.cpp index 64d12ce0d4a..aca0ed19aba 100644 --- a/src/goto-programs/generate_function_bodies.cpp +++ b/src/goto-programs/generate_function_bodies.cpp @@ -8,17 +8,10 @@ Author: Diffblue Ltd. #include "generate_function_bodies.h" -#include -#include -#include -#include - +#include #include #include -#include #include -#include -#include void generate_function_bodiest::generate_function_body( goto_functiont &function, diff --git a/src/goto-programs/goto_functions.h b/src/goto-programs/goto_functions.h index 12b6b8c98be..0289fbdfcc2 100644 --- a/src/goto-programs/goto_functions.h +++ b/src/goto-programs/goto_functions.h @@ -14,14 +14,12 @@ Date: June 2003 #ifndef CPROVER_GOTO_PROGRAMS_GOTO_FUNCTIONS_H #define CPROVER_GOTO_PROGRAMS_GOTO_FUNCTIONS_H -#include "goto_program.h" - -#include -#include +#include -#include -#include #include +#include + +#include "goto_program.h" class goto_functiont { diff --git a/src/goto-programs/goto_program.h b/src/goto-programs/goto_program.h index aa53dfd97d8..88c84258b2f 100644 --- a/src/goto-programs/goto_program.h +++ b/src/goto-programs/goto_program.h @@ -12,7 +12,6 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_GOTO_PROGRAMS_GOTO_PROGRAM_H #define CPROVER_GOTO_PROGRAMS_GOTO_PROGRAM_H -#include #include #include #include diff --git a/src/goto-programs/interpreter_evaluate.cpp b/src/goto-programs/interpreter_evaluate.cpp index 15db12bde80..517f66f050b 100644 --- a/src/goto-programs/interpreter_evaluate.cpp +++ b/src/goto-programs/interpreter_evaluate.cpp @@ -11,16 +11,10 @@ Author: Daniel Kroening, kroening@kroening.com #include "interpreter_class.h" -#include -#include -#include - -#include -#include #include -#include -#include +#include #include +#include #include diff --git a/src/goto-programs/remove_asm.cpp b/src/goto-programs/remove_asm.cpp index d93032a33aa..8df9d6429e8 100644 --- a/src/goto-programs/remove_asm.cpp +++ b/src/goto-programs/remove_asm.cpp @@ -14,14 +14,13 @@ Date: December 2014 #include "remove_asm.h" -#include - #include -#include #include #include +#include "goto_model.h" + class remove_asmt { public: diff --git a/src/goto-programs/remove_asm.h b/src/goto-programs/remove_asm.h index 913fe85c336..49d668c74d9 100644 --- a/src/goto-programs/remove_asm.h +++ b/src/goto-programs/remove_asm.h @@ -15,7 +15,10 @@ Date: December 2014 #ifndef CPROVER_GOTO_PROGRAMS_REMOVE_ASM_H #define CPROVER_GOTO_PROGRAMS_REMOVE_ASM_H -#include +#include + +class goto_modelt; +class symbol_tablet; void remove_asm( goto_functionst::goto_functiont &goto_function, diff --git a/src/goto-programs/remove_calls_no_body.cpp b/src/goto-programs/remove_calls_no_body.cpp index b8e46c41edf..62121dcfe17 100644 --- a/src/goto-programs/remove_calls_no_body.cpp +++ b/src/goto-programs/remove_calls_no_body.cpp @@ -9,9 +9,12 @@ Author: Daniel Poetzl /// \file /// Remove calls to functions without a body -#include #include "remove_calls_no_body.h" +#include + +#include "goto_functions.h" + /// Remove a single call /// \param goto_program: goto program to modify /// \param target: iterator pointing to the call diff --git a/src/goto-programs/remove_calls_no_body.h b/src/goto-programs/remove_calls_no_body.h index de10c426f2e..9b7382328ce 100644 --- a/src/goto-programs/remove_calls_no_body.h +++ b/src/goto-programs/remove_calls_no_body.h @@ -12,7 +12,9 @@ Author: Daniel Poetzl #ifndef CPROVER_GOTO_PROGRAMS_REMOVE_CALLS_NO_BODY_H #define CPROVER_GOTO_PROGRAMS_REMOVE_CALLS_NO_BODY_H -#include "goto_functions.h" +#include "goto_program.h" + +class goto_functionst; class remove_calls_no_bodyt { diff --git a/src/goto-programs/remove_complex.cpp b/src/goto-programs/remove_complex.cpp index 141fc4709fc..ef5b351f54d 100644 --- a/src/goto-programs/remove_complex.cpp +++ b/src/goto-programs/remove_complex.cpp @@ -14,6 +14,10 @@ Date: September 2014 #include "remove_complex.h" #include +#include +#include + +#include "goto_model.h" static exprt complex_member(const exprt &expr, irep_idt id) { diff --git a/src/goto-programs/remove_complex.h b/src/goto-programs/remove_complex.h index 098470ecc1a..c448f4a15e7 100644 --- a/src/goto-programs/remove_complex.h +++ b/src/goto-programs/remove_complex.h @@ -14,7 +14,9 @@ Date: September 2014 #ifndef CPROVER_GOTO_PROGRAMS_REMOVE_COMPLEX_H #define CPROVER_GOTO_PROGRAMS_REMOVE_COMPLEX_H -#include +class goto_functionst; +class goto_modelt; +class symbol_tablet; void remove_complex(symbol_tablet &, goto_functionst &); diff --git a/src/goto-programs/remove_const_function_pointers.cpp b/src/goto-programs/remove_const_function_pointers.cpp index 9b8e67c8b68..81e2812136b 100644 --- a/src/goto-programs/remove_const_function_pointers.cpp +++ b/src/goto-programs/remove_const_function_pointers.cpp @@ -11,9 +11,14 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com #include "remove_const_function_pointers.h" -#include -#include #include +#include +#include +#include + +#include + +#include "goto_functions.h" #define LOG(message, irep) \ debug() << "Case " << __LINE__ << " : " << message << "\n" \ diff --git a/src/goto-programs/remove_const_function_pointers.h b/src/goto-programs/remove_const_function_pointers.h index 469deaec032..0299de8b383 100644 --- a/src/goto-programs/remove_const_function_pointers.h +++ b/src/goto-programs/remove_const_function_pointers.h @@ -12,13 +12,22 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com #ifndef CPROVER_GOTO_PROGRAMS_REMOVE_CONST_FUNCTION_POINTERS_H #define CPROVER_GOTO_PROGRAMS_REMOVE_CONST_FUNCTION_POINTERS_H +#include #include -#include "goto_model.h" -#include #include -#include - +#include +#include + +class address_of_exprt; +class dereference_exprt; +class index_exprt; +class member_exprt; +class namespacet; +class struct_exprt; +class symbol_exprt; +class symbol_tablet; +class typecast_exprt; class remove_const_function_pointerst:public messaget { diff --git a/src/goto-programs/remove_function_pointers.h b/src/goto-programs/remove_function_pointers.h index 3038a940637..4a7bbfb09b5 100644 --- a/src/goto-programs/remove_function_pointers.h +++ b/src/goto-programs/remove_function_pointers.h @@ -14,8 +14,11 @@ Date: June 2003 #ifndef CPROVER_GOTO_PROGRAMS_REMOVE_FUNCTION_POINTERS_H #define CPROVER_GOTO_PROGRAMS_REMOVE_FUNCTION_POINTERS_H -#include "goto_model.h" -#include +class goto_functionst; +class goto_programt; +class goto_modelt; +class message_handlert; +class symbol_tablet; // remove indirect function calls // and replace by case-split diff --git a/src/goto-programs/remove_returns.cpp b/src/goto-programs/remove_returns.cpp index 4c275ff9bbb..5257c83ea0a 100644 --- a/src/goto-programs/remove_returns.cpp +++ b/src/goto-programs/remove_returns.cpp @@ -14,7 +14,8 @@ Date: September 2009 #include "remove_returns.h" #include -#include + +#include "goto_model.h" class remove_returnst { diff --git a/src/goto-programs/remove_returns.h b/src/goto-programs/remove_returns.h index f2017111478..32d2a81c824 100644 --- a/src/goto-programs/remove_returns.h +++ b/src/goto-programs/remove_returns.h @@ -14,10 +14,17 @@ Date: September 2009 #ifndef CPROVER_GOTO_PROGRAMS_REMOVE_RETURNS_H #define CPROVER_GOTO_PROGRAMS_REMOVE_RETURNS_H -#include +#include + +#include #define RETURN_VALUE_SUFFIX "#return_value" +class goto_functionst; +class goto_model_functiont; +class goto_modelt; +class symbol_table_baset; + // Turns 'return x' into an assignment to fkt#return_value, // unless the function returns void, // and a 'goto the_end_of_the_function'. diff --git a/src/goto-programs/remove_skip.h b/src/goto-programs/remove_skip.h index 68f9a833994..6ff55bf3e03 100644 --- a/src/goto-programs/remove_skip.h +++ b/src/goto-programs/remove_skip.h @@ -12,8 +12,9 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_GOTO_PROGRAMS_REMOVE_SKIP_H #define CPROVER_GOTO_PROGRAMS_REMOVE_SKIP_H -#include "goto_functions.h" +#include "goto_program.h" +class goto_functionst; class goto_modelt; bool is_skip(const goto_programt &, goto_programt::const_targett); diff --git a/src/goto-programs/remove_unreachable.cpp b/src/goto-programs/remove_unreachable.cpp index 562546f377b..07d71adf471 100644 --- a/src/goto-programs/remove_unreachable.cpp +++ b/src/goto-programs/remove_unreachable.cpp @@ -14,6 +14,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include "goto_functions.h" + /// remove unreachable code void remove_unreachable(goto_programt &goto_program) { diff --git a/src/goto-programs/remove_unreachable.h b/src/goto-programs/remove_unreachable.h index 5267529d364..ec8ac9bb9fb 100644 --- a/src/goto-programs/remove_unreachable.h +++ b/src/goto-programs/remove_unreachable.h @@ -12,7 +12,8 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_GOTO_PROGRAMS_REMOVE_UNREACHABLE_H #define CPROVER_GOTO_PROGRAMS_REMOVE_UNREACHABLE_H -#include "goto_functions.h" +class goto_functionst; +class goto_programt; void remove_unreachable(goto_programt &goto_program); void remove_unreachable(goto_functionst &goto_functions); diff --git a/src/goto-programs/remove_unused_functions.cpp b/src/goto-programs/remove_unused_functions.cpp index 3092e114796..edb4c712ec2 100644 --- a/src/goto-programs/remove_unused_functions.cpp +++ b/src/goto-programs/remove_unused_functions.cpp @@ -13,6 +13,8 @@ Author: CM Wintersteiger #include +#include "goto_model.h" + void remove_unused_functions( goto_modelt &goto_model, message_handlert &message_handler) diff --git a/src/goto-programs/remove_unused_functions.h b/src/goto-programs/remove_unused_functions.h index 8c8b1739a98..d7fd2569e18 100644 --- a/src/goto-programs/remove_unused_functions.h +++ b/src/goto-programs/remove_unused_functions.h @@ -12,9 +12,14 @@ Author: CM Wintersteiger #ifndef CPROVER_GOTO_PROGRAMS_REMOVE_UNUSED_FUNCTIONS_H #define CPROVER_GOTO_PROGRAMS_REMOVE_UNUSED_FUNCTIONS_H -#include +#include -#include +#include + +class goto_functionst; +class goto_modelt; +class message_handlert; +class symbol_tablet; void remove_unused_functions( goto_functionst &, diff --git a/src/goto-programs/remove_vector.cpp b/src/goto-programs/remove_vector.cpp index f2e7f5b9fe4..cabd5100698 100644 --- a/src/goto-programs/remove_vector.cpp +++ b/src/goto-programs/remove_vector.cpp @@ -14,6 +14,10 @@ Date: September 2014 #include "remove_vector.h" #include +#include +#include + +#include "goto_model.h" static bool have_to_remove_vector(const typet &type); diff --git a/src/goto-programs/remove_vector.h b/src/goto-programs/remove_vector.h index 960d75953a8..2bd1f623e95 100644 --- a/src/goto-programs/remove_vector.h +++ b/src/goto-programs/remove_vector.h @@ -14,7 +14,9 @@ Date: September 2014 #ifndef CPROVER_GOTO_PROGRAMS_REMOVE_VECTOR_H #define CPROVER_GOTO_PROGRAMS_REMOVE_VECTOR_H -#include +class goto_functionst; +class goto_modelt; +class symbol_tablet; void remove_vector(symbol_tablet &, goto_functionst &); diff --git a/src/goto-programs/remove_virtual_functions.cpp b/src/goto-programs/remove_virtual_functions.cpp index 86e19e7de81..a242577e8cd 100644 --- a/src/goto-programs/remove_virtual_functions.cpp +++ b/src/goto-programs/remove_virtual_functions.cpp @@ -8,18 +8,16 @@ Author: Daniel Kroening, kroening@kroening.com /// \file /// Remove Virtual Function (Method) Calls -#include - #include "remove_virtual_functions.h" -#include "class_hierarchy.h" -#include "class_identifier.h" -#include +#include -#include -#include #include +#include "class_identifier.h" +#include "goto_model.h" +#include "resolve_inherited_component.h" + class remove_virtual_functionst { public: diff --git a/src/goto-programs/remove_virtual_functions.h b/src/goto-programs/remove_virtual_functions.h index 43bd0f2fea8..ae5d257f6fd 100644 --- a/src/goto-programs/remove_virtual_functions.h +++ b/src/goto-programs/remove_virtual_functions.h @@ -14,8 +14,15 @@ Date: April 2016 #ifndef CPROVER_GOTO_PROGRAMS_REMOVE_VIRTUAL_FUNCTIONS_H #define CPROVER_GOTO_PROGRAMS_REMOVE_VIRTUAL_FUNCTIONS_H -#include "goto_model.h" +#include + #include "class_hierarchy.h" +#include "goto_program.h" + +class goto_functionst; +class goto_model_functiont; +class goto_modelt; +class symbol_table_baset; // remove virtual function calls // and replace by case-split diff --git a/src/goto-programs/string_abstraction.cpp b/src/goto-programs/string_abstraction.cpp index fd5a123c6df..5a9043cff2b 100644 --- a/src/goto-programs/string_abstraction.cpp +++ b/src/goto-programs/string_abstraction.cpp @@ -16,14 +16,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include -#include -#include -#include -#include #include -#include - #include "pointer_arithmetic.h" bool string_abstractiont::build_wrap( diff --git a/src/goto-programs/vcd_goto_trace.cpp b/src/goto-programs/vcd_goto_trace.cpp index 7acc15e890b..9e736033df1 100644 --- a/src/goto-programs/vcd_goto_trace.cpp +++ b/src/goto-programs/vcd_goto_trace.cpp @@ -13,13 +13,11 @@ Date: June 2011 #include "vcd_goto_trace.h" -#include -#include #include +#include -#include -#include #include +#include std::string as_vcd_binary( const exprt &expr, diff --git a/src/goto-symex/equation_conversion_exceptions.h b/src/goto-symex/equation_conversion_exceptions.h index f2055c1c9ec..ffa57abefe0 100644 --- a/src/goto-symex/equation_conversion_exceptions.h +++ b/src/goto-symex/equation_conversion_exceptions.h @@ -12,7 +12,7 @@ Author: Diffblue Ltd. #ifndef CPROVER_GOTO_SYMEX_EQUATION_CONVERSION_EXCEPTIONS_H #define CPROVER_GOTO_SYMEX_EQUATION_CONVERSION_EXCEPTIONS_H -#include +#include #include diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h index 7d7edb8891f..117693b8391 100644 --- a/src/goto-symex/goto_symex.h +++ b/src/goto-symex/goto_symex.h @@ -14,13 +14,13 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include #include #include "goto_symex_state.h" #include "symex_target_equation.h" +class byte_extract_exprt; class typet; class code_typet; class symbol_tablet; diff --git a/src/goto-symex/symex_builtin_functions.cpp b/src/goto-symex/symex_builtin_functions.cpp index 6294e47b3a1..f827f1ecaea 100644 --- a/src/goto-symex/symex_builtin_functions.cpp +++ b/src/goto-symex/symex_builtin_functions.cpp @@ -11,25 +11,15 @@ Author: Daniel Kroening, kroening@kroening.com #include "goto_symex.h" -#include -#include #include -#include -#include +#include +#include #include -#include -#include -#include #include -#include #include -#include -#include #include -#include "goto_symex_state.h" - inline static typet c_sizeof_type_rec(const exprt &expr) { const irept &sizeof_type=expr.find(ID_C_c_sizeof_type); diff --git a/src/goto-symex/symex_clean_expr.cpp b/src/goto-symex/symex_clean_expr.cpp index 5e1e0cf4c91..ce6265e1c20 100644 --- a/src/goto-symex/symex_clean_expr.cpp +++ b/src/goto-symex/symex_clean_expr.cpp @@ -12,11 +12,10 @@ Author: Daniel Kroening, kroening@kroening.com #include "goto_symex.h" #include -#include -#include #include -#include +#include #include +#include /// Given an expression, find the root object and the offset into it. /// diff --git a/src/goto-symex/symex_dereference.cpp b/src/goto-symex/symex_dereference.cpp index 95b8866865e..e259a515489 100644 --- a/src/goto-symex/symex_dereference.cpp +++ b/src/goto-symex/symex_dereference.cpp @@ -11,16 +11,14 @@ Author: Daniel Kroening, kroening@kroening.com #include "goto_symex.h" -#include -#include #include #include #include +#include +#include +#include #include -#include - -#include #include "symex_dereference_state.h" diff --git a/src/goto-symex/symex_function_call.cpp b/src/goto-symex/symex_function_call.cpp index 37e173928c4..6de8995364d 100644 --- a/src/goto-symex/symex_function_call.cpp +++ b/src/goto-symex/symex_function_call.cpp @@ -11,19 +11,11 @@ Author: Daniel Kroening, kroening@kroening.com #include "goto_symex.h" -#include - -#include -#include -#include #include #include -#include -#include - +#include #include - -#include +#include bool goto_symext::get_unwind_recursion( const irep_idt &identifier, diff --git a/src/goto-symex/symex_other.cpp b/src/goto-symex/symex_other.cpp index f3cc50c32bb..30ca539f429 100644 --- a/src/goto-symex/symex_other.cpp +++ b/src/goto-symex/symex_other.cpp @@ -12,14 +12,10 @@ Author: Daniel Kroening, kroening@kroening.com #include "goto_symex.h" #include -#include -#include #include -#include -#include #include -#include #include +#include void goto_symext::havoc_rec( statet &state, diff --git a/src/java_bytecode/java_entry_point.cpp b/src/java_bytecode/java_entry_point.cpp index ef4a4e70cc8..2556ee4d7e9 100644 --- a/src/java_bytecode/java_entry_point.cpp +++ b/src/java_bytecode/java_entry_point.cpp @@ -8,31 +8,15 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_entry_point.h" -#include -#include -#include -#include - -#include - -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include #include #include +#include + #include #include "java_object_factory.h" -#include "java_types.h" #include "java_utils.h" static void create_initialize(symbol_table_baset &symbol_table) diff --git a/src/java_bytecode/java_object_factory.cpp b/src/java_bytecode/java_object_factory.cpp index feaeb218f6c..612a66f9ce5 100644 --- a/src/java_bytecode/java_object_factory.cpp +++ b/src/java_bytecode/java_object_factory.cpp @@ -8,32 +8,14 @@ Author: Daniel Kroening, kroening@kroening.com #include "java_object_factory.h" -#include -#include - -#include #include -#include -#include -#include -#include #include -#include #include -#include -#include - -#include #include -#include - -#include "java_types.h" -#include "java_utils.h" -#include "java_string_library_preprocess.h" -#include "java_root_class.h" #include "generic_parameter_specialization_map_keys.h" +#include "java_root_class.h" class java_object_factoryt { diff --git a/src/jsil/jsil_entry_point.cpp b/src/jsil/jsil_entry_point.cpp index a8f1278e961..43f60bd1950 100644 --- a/src/jsil/jsil_entry_point.cpp +++ b/src/jsil/jsil_entry_point.cpp @@ -13,10 +13,7 @@ Author: Michael Tautschnig, tautschn@amazon.com #include #include -#include #include -#include -#include #include diff --git a/src/linking/linking.cpp b/src/linking/linking.cpp index 5b5a1d36fd2..a93e0919e64 100644 --- a/src/linking/linking.cpp +++ b/src/linking/linking.cpp @@ -12,15 +12,13 @@ Author: Daniel Kroening, kroening@kroening.com #include "linking.h" #include -#include +#include +#include -#include -#include #include -#include -#include -#include +#include #include +#include #include diff --git a/src/linking/remove_internal_symbols.cpp b/src/linking/remove_internal_symbols.cpp index 91f6e3c411d..d563278ff52 100644 --- a/src/linking/remove_internal_symbols.cpp +++ b/src/linking/remove_internal_symbols.cpp @@ -11,12 +11,11 @@ Author: Daniel Kroening #include "remove_internal_symbols.h" -#include -#include +#include #include +#include #include -#include -#include +#include #include "static_lifetime_init.h" diff --git a/src/linking/static_lifetime_init.h b/src/linking/static_lifetime_init.h index 0955fc1f57c..829e2e16a05 100644 --- a/src/linking/static_lifetime_init.h +++ b/src/linking/static_lifetime_init.h @@ -10,11 +10,12 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_LINKING_STATIC_LIFETIME_INIT_H #define CPROVER_LINKING_STATIC_LIFETIME_INIT_H -#include -#include -#include #include +class message_handlert; +class source_locationt; +class symbol_tablet; + bool static_lifetime_init( symbol_tablet &symbol_table, const source_locationt &source_location, diff --git a/src/linking/zero_initializer.cpp b/src/linking/zero_initializer.cpp index 0916256ab5d..675cdb7dd7f 100644 --- a/src/linking/zero_initializer.cpp +++ b/src/linking/zero_initializer.cpp @@ -11,16 +11,13 @@ Author: Daniel Kroening, kroening@kroening.com #include "zero_initializer.h" -#include - -#include -#include #include -#include -#include +#include +#include +#include #include +#include -#include #include class zero_initializert:public messaget diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp index 0e528f5760b..7cd08339d7a 100644 --- a/src/pointer-analysis/value_set.cpp +++ b/src/pointer-analysis/value_set.cpp @@ -14,17 +14,11 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include -#include -#include -#include -#include -#include #include -#include -#include - +#include #include +#include +#include #include diff --git a/src/pointer-analysis/value_set_dereference.cpp b/src/pointer-analysis/value_set_dereference.cpp index 4e437ede5ea..3e6e653d7a7 100644 --- a/src/pointer-analysis/value_set_dereference.cpp +++ b/src/pointer-analysis/value_set_dereference.cpp @@ -16,35 +16,23 @@ Author: Daniel Kroening, kroening@kroening.com #include #endif -#include -#include - -#include -#include -#include -#include -#include #include -#include #include +#include +#include +#include #include -#include #include -#include -#include +#include #include #include +#include #include -#include +#include #include -#include #include -#include - -#include "pointer_offset_sum.h" - // global data, horrible unsigned int value_set_dereferencet::invalid_counter=0; diff --git a/src/solvers/flattening/boolbv_update.cpp b/src/solvers/flattening/boolbv_update.cpp index f5121f8bf91..668b8cc8fdc 100644 --- a/src/solvers/flattening/boolbv_update.cpp +++ b/src/solvers/flattening/boolbv_update.cpp @@ -8,13 +8,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "boolbv.h" -#include -#include #include -#include -#include - -#include bvt boolbvt::convert_update(const exprt &expr) { diff --git a/src/solvers/flattening/bv_pointers.cpp b/src/solvers/flattening/bv_pointers.cpp index b82a54ac615..7043938eccf 100644 --- a/src/solvers/flattening/bv_pointers.cpp +++ b/src/solvers/flattening/bv_pointers.cpp @@ -8,14 +8,10 @@ Author: Daniel Kroening, kroening@kroening.com #include "bv_pointers.h" +#include #include #include -#include -#include -#include -#include #include -#include literalt bv_pointerst::convert_rest(const exprt &expr) { diff --git a/src/solvers/flattening/flatten_byte_operators.cpp b/src/solvers/flattening/flatten_byte_operators.cpp index 42054cc61dc..2cc586c7c02 100644 --- a/src/solvers/flattening/flatten_byte_operators.cpp +++ b/src/solvers/flattening/flatten_byte_operators.cpp @@ -6,19 +6,17 @@ Author: Daniel Kroening, kroening@kroening.com \*******************************************************************/ -#include -#include -#include -#include +#include "flatten_byte_operators.h" + #include -#include #include +#include #include +#include #include #include #include "flatten_byte_extract_exceptions.h" -#include "flatten_byte_operators.h" /// rewrite an object into its individual bytes /// \par parameters: src object to unpack diff --git a/src/solvers/flattening/pointer_logic.cpp b/src/solvers/flattening/pointer_logic.cpp index 5bbbad458f2..d0a2a866903 100644 --- a/src/solvers/flattening/pointer_logic.cpp +++ b/src/solvers/flattening/pointer_logic.cpp @@ -15,9 +15,10 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include -#include +#include #include +#include +#include bool pointer_logict::is_dynamic_object(const exprt &expr) const { diff --git a/src/util/base_type.cpp b/src/util/base_type.cpp index 4aba15b5505..d32a2836aaf 100644 --- a/src/util/base_type.cpp +++ b/src/util/base_type.cpp @@ -11,11 +11,10 @@ Author: Daniel Kroening, kroening@kroening.com #include "base_type.h" -#include #include -#include "std_types.h" #include "namespace.h" +#include "std_types.h" #include "symbol.h" #include "union_find.h" diff --git a/src/util/fresh_symbol.cpp b/src/util/fresh_symbol.cpp index 0f7c3a9daf2..c77c7e33e47 100644 --- a/src/util/fresh_symbol.cpp +++ b/src/util/fresh_symbol.cpp @@ -13,6 +13,8 @@ Author: Chris Smowton, chris.smowton@diffblue.com #include "namespace.h" #include "rename.h" +#include "symbol.h" +#include "symbol_table_base.h" /// Installs a fresh-named symbol with the requested name pattern /// \par parameters: `type`: type of new symbol diff --git a/src/util/fresh_symbol.h b/src/util/fresh_symbol.h index 8cdedc56977..0d1601ad180 100644 --- a/src/util/fresh_symbol.h +++ b/src/util/fresh_symbol.h @@ -14,10 +14,12 @@ Author: Chris Smowton, chris.smowton@diffblue.com #include -#include -#include -#include -#include +#include "irep.h" + +class source_locationt; +class symbolt; +class symbol_table_baset; +class typet; symbolt &get_fresh_aux_symbol( const typet &type, diff --git a/src/util/graph.h b/src/util/graph.h index 85ad33c448d..6b7fd6e07f7 100644 --- a/src/util/graph.h +++ b/src/util/graph.h @@ -12,15 +12,15 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_UTIL_GRAPH_H #define CPROVER_UTIL_GRAPH_H +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include #include -#include +#include +#include #include "invariant.h" diff --git a/src/util/invariant_utils.h b/src/util/invariant_utils.h index d448fedfeb3..3dd9d386418 100644 --- a/src/util/invariant_utils.h +++ b/src/util/invariant_utils.h @@ -10,8 +10,7 @@ Author: Chris Smowton, chris.smowton@diffblue.com #define CPROVER_UTIL_INVARIANT_TYPES_H #include "invariant.h" - -#include +#include "irep.h" #include diff --git a/src/util/irep.h b/src/util/irep.h index fbaf0ad5a94..2365989bfaa 100644 --- a/src/util/irep.h +++ b/src/util/irep.h @@ -12,8 +12,6 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include -#include #include "irep_ids.h" diff --git a/src/util/irep_hash_container.h b/src/util/irep_hash_container.h index 382130659e0..65342ba99b1 100644 --- a/src/util/irep_hash_container.h +++ b/src/util/irep_hash_container.h @@ -12,7 +12,6 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_UTIL_IREP_HASH_CONTAINER_H #define CPROVER_UTIL_IREP_HASH_CONTAINER_H -#include // for size_t #include #include "numbering.h" @@ -22,7 +21,7 @@ class irept; class irep_hash_container_baset { public: - size_t number(const irept &irep); + std::size_t number(const irept &irep); explicit irep_hash_container_baset(bool _full):full(_full) { @@ -41,23 +40,23 @@ class irep_hash_container_baset struct pointer_hasht { - size_t operator()(const void *p) const + std::size_t operator()(const void *p) const { - return (size_t)p; + return (std::size_t)p; } }; - typedef std::unordered_map + typedef std::unordered_map ptr_hasht; ptr_hasht ptr_hash; // this is the second level: content - typedef std::vector packedt; + typedef std::vector packedt; struct vector_hasht { - size_t operator()(const packedt &p) const; + std::size_t operator()(const packedt &p) const; }; typedef hash_numbering numberingt; diff --git a/src/util/json_irep.h b/src/util/json_irep.h index 6fdc3dfc92d..6e6fe6b1a55 100644 --- a/src/util/json_irep.h +++ b/src/util/json_irep.h @@ -12,7 +12,7 @@ Author: Thomas Kiley, thomas.kiley@diffblue.com #ifndef CPROVER_UTIL_JSON_IREP_H #define CPROVER_UTIL_JSON_IREP_H -#include +#include "irep.h" class jsont; class json_objectt; diff --git a/src/util/json_stream.h b/src/util/json_stream.h index f27e360c9a3..cbb4689a5de 100644 --- a/src/util/json_stream.h +++ b/src/util/json_stream.h @@ -9,8 +9,8 @@ Author: Peter Schrammel #ifndef CPROVER_UTIL_JSON_STREAM_H #define CPROVER_UTIL_JSON_STREAM_H -#include #include +#include #include "json.h" #include "invariant.h" diff --git a/src/util/nondet_bool.h b/src/util/nondet_bool.h index af628d3456e..700b85ec5b0 100644 --- a/src/util/nondet_bool.h +++ b/src/util/nondet_bool.h @@ -12,8 +12,8 @@ Author: Chris Smowton, chris@smowton.net #ifndef CPROVER_UTIL_NONDET_BOOL_H #define CPROVER_UTIL_NONDET_BOOL_H -#include -#include +#include "std_expr.h" +#include "std_types.h" /// \par parameters: Desired type (C_bool or plain bool) /// \return nondet expr of that type diff --git a/src/util/nondet_ifthenelse.h b/src/util/nondet_ifthenelse.h index 664a6bdf1b2..cf1966526ef 100644 --- a/src/util/nondet_ifthenelse.h +++ b/src/util/nondet_ifthenelse.h @@ -12,7 +12,7 @@ Author: Chris Smowton, chris@smowton.net #ifndef CPROVER_UTIL_NONDET_IFTHENELSE_H #define CPROVER_UTIL_NONDET_IFTHENELSE_H -#include +#include "std_code.h" class symbol_tablet; class source_locationt; diff --git a/src/util/numbering.h b/src/util/numbering.h index f932874695a..42e18354e21 100644 --- a/src/util/numbering.h +++ b/src/util/numbering.h @@ -9,13 +9,12 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_UTIL_NUMBERING_H #define CPROVER_UTIL_NUMBERING_H -#include #include #include #include -#include -#include +#include "invariant.h" +#include "optional.h" /// \tparam Map a map from a key type to some numeric type template diff --git a/src/util/pointer_offset_size.cpp b/src/util/pointer_offset_size.cpp index 21dbdbb23f7..2e315ba242f 100644 --- a/src/util/pointer_offset_size.cpp +++ b/src/util/pointer_offset_size.cpp @@ -11,17 +11,13 @@ Author: Daniel Kroening, kroening@kroening.com #include "pointer_offset_size.h" +#include "arith_tools.h" #include "c_types.h" -#include "expr.h" #include "invariant.h" -#include "arith_tools.h" -#include "std_types.h" -#include "std_expr.h" -#include "expr_util.h" -#include "simplify_expr.h" #include "namespace.h" -#include "symbol.h" +#include "simplify_expr.h" #include "ssa_expr.h" +#include "std_expr.h" member_offset_iterator::member_offset_iterator( const struct_typet &_type, diff --git a/src/util/pointer_predicates.cpp b/src/util/pointer_predicates.cpp index 312166f0088..966ebdae021 100644 --- a/src/util/pointer_predicates.cpp +++ b/src/util/pointer_predicates.cpp @@ -11,14 +11,12 @@ Author: Daniel Kroening, kroening@kroening.com #include "pointer_predicates.h" +#include "arith_tools.h" #include "c_types.h" #include "cprover_prefix.h" #include "namespace.h" -#include "std_expr.h" -#include "expr_util.h" -#include "arith_tools.h" #include "pointer_offset_size.h" -#include "config.h" +#include "std_expr.h" #include "symbol.h" exprt pointer_object(const exprt &p) diff --git a/src/util/rational.h b/src/util/rational.h index 809f237c95a..a043ed0923d 100644 --- a/src/util/rational.h +++ b/src/util/rational.h @@ -10,9 +10,6 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_UTIL_RATIONAL_H #define CPROVER_UTIL_RATIONAL_H -#include -#include - #include "mp_arith.h" class constant_exprt; diff --git a/src/util/refined_string_type.cpp b/src/util/refined_string_type.cpp index 818eb9e4391..91cbc7ff090 100644 --- a/src/util/refined_string_type.cpp +++ b/src/util/refined_string_type.cpp @@ -18,6 +18,8 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com #include "refined_string_type.h" +#include "std_expr.h" + refined_string_typet::refined_string_typet( const typet &index_type, const typet &char_type) { diff --git a/src/util/refined_string_type.h b/src/util/refined_string_type.h index ecef73288ea..bc597556b2d 100644 --- a/src/util/refined_string_type.h +++ b/src/util/refined_string_type.h @@ -19,11 +19,8 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com #ifndef CPROVER_UTIL_REFINED_STRING_TYPE_H #define CPROVER_UTIL_REFINED_STRING_TYPE_H -#include -#include -#include -#include -#include +#include "cprover_prefix.h" +#include "std_types.h" // Internal type used for string refinement class refined_string_typet: public struct_typet diff --git a/src/util/sharing_map.h b/src/util/sharing_map.h index a558ec42901..1c8943ae1ac 100644 --- a/src/util/sharing_map.h +++ b/src/util/sharing_map.h @@ -15,17 +15,15 @@ Author: Daniel Poetzl #include #include #include -#include #include #include #include #include #include -#include -#include -#include -#include +#include "irep.h" +#include "sharing_node.h" +#include "threeval.h" #define _sm_assert(b) assert(b) //#define _sm_assert(b) diff --git a/src/util/sharing_node.h b/src/util/sharing_node.h index 9cec1cd2f3a..2ecebabb467 100644 --- a/src/util/sharing_node.h +++ b/src/util/sharing_node.h @@ -15,7 +15,6 @@ Author: Daniel Poetzl #include #include #include -#include #include "invariant.h" diff --git a/src/util/simplify_expr.cpp b/src/util/simplify_expr.cpp index 4a0e2855d29..c2e07be9630 100644 --- a/src/util/simplify_expr.cpp +++ b/src/util/simplify_expr.cpp @@ -11,29 +11,21 @@ Author: Daniel Kroening, kroening@kroening.com #include #include -#include "c_types.h" -#include "rational.h" -#include "simplify_expr_class.h" -#include "mp_arith.h" #include "arith_tools.h" -#include "replace_expr.h" -#include "std_types.h" +#include "base_type.h" +#include "byte_operators.h" +#include "c_types.h" +#include "config.h" +#include "endianness_map.h" #include "expr_util.h" -#include "std_expr.h" #include "fixedbv.h" +#include "namespace.h" #include "pointer_offset_size.h" +#include "rational.h" #include "rational_tools.h" -#include "config.h" -#include "base_type.h" -#include "type_eq.h" -#include "namespace.h" -#include "threeval.h" -#include "pointer_predicates.h" -#include "prefix.h" -#include "byte_operators.h" -#include "bv_arithmetic.h" -#include "endianness_map.h" #include "simplify_utils.h" +#include "std_expr.h" +#include "type_eq.h" // #define DEBUGX @@ -41,6 +33,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #endif +#include "simplify_expr_class.h" + // #define USE_CACHE #ifdef USE_CACHE diff --git a/src/util/simplify_expr_array.cpp b/src/util/simplify_expr_array.cpp index 026cb84105f..db64a51b243 100644 --- a/src/util/simplify_expr_array.cpp +++ b/src/util/simplify_expr_array.cpp @@ -8,14 +8,11 @@ Author: Daniel Kroening, kroening@kroening.com #include "simplify_expr_class.h" -#include - -#include "expr.h" -#include "namespace.h" -#include "std_expr.h" -#include "replace_expr.h" #include "arith_tools.h" +#include "namespace.h" #include "pointer_offset_size.h" +#include "replace_expr.h" +#include "std_expr.h" bool simplify_exprt::simplify_index(exprt &expr) { diff --git a/src/util/simplify_expr_int.cpp b/src/util/simplify_expr_int.cpp index c225997d2c8..da3c03da448 100644 --- a/src/util/simplify_expr_int.cpp +++ b/src/util/simplify_expr_int.cpp @@ -14,7 +14,6 @@ Author: Daniel Kroening, kroening@kroening.com #include "base_type.h" #include "bv_arithmetic.h" #include "config.h" -#include "expr.h" #include "expr_util.h" #include "fixedbv.h" #include "ieee_float.h" @@ -24,7 +23,6 @@ Author: Daniel Kroening, kroening@kroening.com #include "rational.h" #include "rational_tools.h" #include "std_expr.h" -#include "string2int.h" bool simplify_exprt::simplify_bswap(bswap_exprt &expr) { diff --git a/src/util/simplify_expr_pointer.cpp b/src/util/simplify_expr_pointer.cpp index a1e26187897..fff9ba57f52 100644 --- a/src/util/simplify_expr_pointer.cpp +++ b/src/util/simplify_expr_pointer.cpp @@ -10,17 +10,15 @@ Author: Daniel Kroening, kroening@kroening.com #include -#include "c_types.h" -#include "expr.h" -#include "namespace.h" -#include "std_expr.h" -#include "pointer_offset_size.h" #include "arith_tools.h" +#include "c_types.h" #include "config.h" #include "expr_util.h" -#include "threeval.h" -#include "prefix.h" +#include "namespace.h" +#include "pointer_offset_size.h" #include "pointer_predicates.h" +#include "std_expr.h" +#include "threeval.h" static bool is_dereference_integer_object( const exprt &expr, diff --git a/src/util/simplify_expr_struct.cpp b/src/util/simplify_expr_struct.cpp index e6195f2cb54..331d04c3001 100644 --- a/src/util/simplify_expr_struct.cpp +++ b/src/util/simplify_expr_struct.cpp @@ -8,15 +8,12 @@ Author: Daniel Kroening, kroening@kroening.com #include "simplify_expr_class.h" -#include - +#include "arith_tools.h" +#include "base_type.h" #include "byte_operators.h" -#include "expr.h" #include "namespace.h" -#include "std_expr.h" #include "pointer_offset_size.h" -#include "arith_tools.h" -#include "base_type.h" +#include "std_expr.h" bool simplify_exprt::simplify_member(exprt &expr) { diff --git a/src/util/ssa_expr.h b/src/util/ssa_expr.h index 63e6dfaf7d7..3a0e3b151d6 100644 --- a/src/util/ssa_expr.h +++ b/src/util/ssa_expr.h @@ -10,7 +10,7 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_UTIL_SSA_EXPR_H #define CPROVER_UTIL_SSA_EXPR_H -#include +#include "std_expr.h" /*! \brief Expression providing an SSA-renamed symbol of expressions */ diff --git a/src/util/std_expr.cpp b/src/util/std_expr.cpp index 445c31c3c27..431ca387530 100644 --- a/src/util/std_expr.cpp +++ b/src/util/std_expr.cpp @@ -13,9 +13,7 @@ Author: Daniel Kroening, kroening@kroening.com #include "arith_tools.h" #include "byte_operators.h" #include "c_types.h" -#include "namespace.h" #include "pointer_offset_size.h" -#include "std_types.h" bool constant_exprt::value_is_zero_string() const { diff --git a/src/util/string_expr.h b/src/util/string_expr.h index c9d54470d3b..dd44684140f 100644 --- a/src/util/string_expr.h +++ b/src/util/string_expr.h @@ -12,9 +12,9 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com #ifndef CPROVER_UTIL_STRING_EXPR_H #define CPROVER_UTIL_STRING_EXPR_H -#include -#include -#include +#include "arith_tools.h" +#include "refined_string_type.h" +#include "std_expr.h" // Given an representation of strings as exprt that implements `length` and // `content` this provides additional useful methods. diff --git a/src/util/symbol_table_base.h b/src/util/symbol_table_base.h index 62db57c024c..6a51a34a863 100644 --- a/src/util/symbol_table_base.h +++ b/src/util/symbol_table_base.h @@ -6,13 +6,9 @@ #ifndef CPROVER_UTIL_SYMBOL_TABLE_BASE_H #define CPROVER_UTIL_SYMBOL_TABLE_BASE_H -#include -#include #include #include -#include - #include "symbol.h" typedef std::multimap symbol_base_mapt; diff --git a/src/util/union_find_replace.h b/src/util/union_find_replace.h index 37f86604f1b..b7630db11ed 100644 --- a/src/util/union_find_replace.h +++ b/src/util/union_find_replace.h @@ -9,7 +9,7 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com #ifndef CPROVER_UTIL_UNION_FIND_REPLACE_H #define CPROVER_UTIL_UNION_FIND_REPLACE_H -#include +#include "replace_expr.h" /// Similar interface to union-find for expressions, with a function for /// replacing sub-expressions by their result for find. From 5fcd098412f30ba2445862cb4fd1f5cf4c0af6c2 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sat, 28 Apr 2018 13:56:54 +0100 Subject: [PATCH 82/93] Assign mode to invalid objects --- src/pointer-analysis/value_set_dereference.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pointer-analysis/value_set_dereference.cpp b/src/pointer-analysis/value_set_dereference.cpp index 3e6e653d7a7..8b2ed99baab 100644 --- a/src/pointer-analysis/value_set_dereference.cpp +++ b/src/pointer-analysis/value_set_dereference.cpp @@ -153,6 +153,7 @@ exprt value_set_dereferencet::dereference( symbol.name="symex::invalid_object"+std::to_string(invalid_counter++); symbol.base_name="invalid_object"; symbol.type=type; + symbol.mode = language_mode; // make it a lvalue, so we can assign to it symbol.is_lvalue=true; From 81331c89d446095208b7fc0e65f8b8b0d3357a2b Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Sat, 28 Apr 2018 15:09:27 +0100 Subject: [PATCH 83/93] whitespace fix --- src/cbmc/bmc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cbmc/bmc.cpp b/src/cbmc/bmc.cpp index 545ab8a54f1..205e738d392 100644 --- a/src/cbmc/bmc.cpp +++ b/src/cbmc/bmc.cpp @@ -374,9 +374,9 @@ safety_checkert::resultt bmct::execute( (*memory_model)(equation); } - statistics() << "size of program expression: " - << equation.SSA_steps.size() - << " steps" << eom; + statistics() << "size of program expression: " + << equation.SSA_steps.size() + << " steps" << eom; slice(); From 9111c4dc4a1f3ec7ec4e6aa0d75d12f46587f940 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Sat, 28 Apr 2018 15:50:58 +0100 Subject: [PATCH 84/93] remove do_unwind_module hook --- src/cbmc/bmc.cpp | 8 -------- src/cbmc/bmc.h | 1 - 2 files changed, 9 deletions(-) diff --git a/src/cbmc/bmc.cpp b/src/cbmc/bmc.cpp index 205e738d392..e236091631a 100644 --- a/src/cbmc/bmc.cpp +++ b/src/cbmc/bmc.cpp @@ -35,11 +35,6 @@ Author: Daniel Kroening, kroening@kroening.com #include "counterexample_beautification.h" #include "fault_localization.h" -void bmct::do_unwind_module() -{ - // this is a hook for hw-cbmc -} - /// Hook used by CEGIS to selectively freeze variables /// in the SAT solver after the SSA formula is added to the solver. /// Freezing variables is necessary to make use of incremental @@ -118,9 +113,6 @@ void bmct::output_graphml(resultt result) void bmct::do_conversion() { - // convert HDL (hook for hw-cbmc) - do_unwind_module(); - status() << "converting SSA" << eom; // convert SSA diff --git a/src/cbmc/bmc.h b/src/cbmc/bmc.h index 0f394199fe0..7401a641155 100644 --- a/src/cbmc/bmc.h +++ b/src/cbmc/bmc.h @@ -191,7 +191,6 @@ class bmct:public safety_checkert // unwinding virtual void setup_unwind(); - virtual void do_unwind_module(); void do_conversion(); virtual void freeze_program_variables(); From 879e3797bf2ef5b72e62a7b51327dae2457a08b5 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Sat, 28 Apr 2018 15:53:24 +0100 Subject: [PATCH 85/93] remove unused includes --- src/cbmc/bmc.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/cbmc/bmc.h b/src/cbmc/bmc.h index 7401a641155..907c9bdd4fd 100644 --- a/src/cbmc/bmc.h +++ b/src/cbmc/bmc.h @@ -18,13 +18,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include - -#include -#include -#include -#include -#include -#include +#include #include From cbc4fa265fdf464861402f8f4cda5b7a84edb7e6 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Sat, 28 Apr 2018 14:42:20 +0100 Subject: [PATCH 86/93] remove support for SMT1 --- src/cbmc/cbmc_parse_options.cpp | 58 +- src/cbmc/cbmc_solvers.cpp | 99 - src/cbmc/cbmc_solvers.h | 5 - src/solvers/Makefile | 2 - src/solvers/smt1/smt1_conv.cpp | 3215 ------------------------------- src/solvers/smt1/smt1_conv.h | 213 -- src/solvers/smt1/smt1_dec.cpp | 667 ------- src/solvers/smt1/smt1_dec.h | 75 - 8 files changed, 11 insertions(+), 4323 deletions(-) delete mode 100644 src/solvers/smt1/smt1_conv.cpp delete mode 100644 src/solvers/smt1/smt1_conv.h delete mode 100644 src/solvers/smt1/smt1_dec.cpp delete mode 100644 src/solvers/smt1/smt1_dec.h diff --git a/src/cbmc/cbmc_parse_options.cpp b/src/cbmc/cbmc_parse_options.cpp index e7189f965d1..3eb08b6fd9a 100644 --- a/src/cbmc/cbmc_parse_options.cpp +++ b/src/cbmc/cbmc_parse_options.cpp @@ -312,100 +312,64 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options) options.set_option("aig", true); // SMT Options - bool version_set=false; if(cmdline.isset("smt1")) { - options.set_option("smt1", true); - options.set_option("smt2", false); - version_set=true; + error() << "--smt1 is no longer supported" << eom; + exit(CPROVER_EXIT_USAGE_ERROR); } if(cmdline.isset("smt2")) - { - // If both are given, smt2 takes precedence - options.set_option("smt1", false); options.set_option("smt2", true); - version_set=true; - } if(cmdline.isset("fpa")) options.set_option("fpa", true); - bool solver_set=false; if(cmdline.isset("boolector")) { options.set_option("boolector", true), solver_set=true; - if(!version_set) - options.set_option("smt2", true), version_set=true; + options.set_option("smt2", true); } if(cmdline.isset("mathsat")) { options.set_option("mathsat", true), solver_set=true; - if(!version_set) - options.set_option("smt2", true), version_set=true; - } - - if(cmdline.isset("cvc3")) - { - options.set_option("cvc3", true), solver_set=true; - if(!version_set) - options.set_option("smt1", true), version_set=true; + options.set_option("smt2", true); } if(cmdline.isset("cvc4")) { options.set_option("cvc4", true), solver_set=true; - if(!version_set) - options.set_option("smt2", true), version_set=true; + options.set_option("smt2", true); } if(cmdline.isset("yices")) { options.set_option("yices", true), solver_set=true; - if(!version_set) - options.set_option("smt2", true), version_set=true; + options.set_option("smt2", true); } if(cmdline.isset("z3")) { options.set_option("z3", true), solver_set=true; - if(!version_set) - options.set_option("smt2", true), version_set=true; - } - - if(cmdline.isset("opensmt")) - { - options.set_option("opensmt", true), solver_set=true; - if(!version_set) - options.set_option("smt1", true), version_set=true; + options.set_option("smt2", true); } - if(version_set && !solver_set) + if(cmdline.isset("smt2") && !solver_set) { if(cmdline.isset("outfile")) { // outfile and no solver should give standard compliant SMT-LIB - options.set_option("generic", true), solver_set=true; + options.set_option("generic", true); } else { - if(options.get_bool_option("smt1")) - { - options.set_option("boolector", true), solver_set=true; - } - else - { - PRECONDITION(options.get_bool_option("smt2")); - options.set_option("z3", true), solver_set=true; - } + // the default smt2 solver + options.set_option("z3", true); } } - // Either have solver and standard version set, or neither. - PRECONDITION(version_set == solver_set); if(cmdline.isset("beautify")) options.set_option("beautify", true); diff --git a/src/cbmc/cbmc_solvers.cpp b/src/cbmc/cbmc_solvers.cpp index ed5787af6d3..4195ad5fca8 100644 --- a/src/cbmc/cbmc_solvers.cpp +++ b/src/cbmc/cbmc_solvers.cpp @@ -21,7 +21,6 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include -#include #include #include #include @@ -32,34 +31,6 @@ Author: Daniel Kroening, kroening@kroening.com #include "counterexample_beautification.h" #include "version.h" -/// Uses the options to pick an SMT 1.2 solver -/// \return An smt1_dect::solvert giving the solver to use. -smt1_dect::solvert cbmc_solverst::get_smt1_solver_type() const -{ - assert(options.get_bool_option("smt1")); - - smt1_dect::solvert s=smt1_dect::solvert::GENERIC; - - if(options.get_bool_option("boolector")) - s=smt1_dect::solvert::BOOLECTOR; - else if(options.get_bool_option("mathsat")) - s=smt1_dect::solvert::MATHSAT; - else if(options.get_bool_option("cvc3")) - s=smt1_dect::solvert::CVC3; - else if(options.get_bool_option("cvc4")) - s=smt1_dect::solvert::CVC4; - else if(options.get_bool_option("opensmt")) - s=smt1_dect::solvert::OPENSMT; - else if(options.get_bool_option("yices")) - s=smt1_dect::solvert::YICES; - else if(options.get_bool_option("z3")) - s=smt1_dect::solvert::Z3; - else if(options.get_bool_option("generic")) - s=smt1_dect::solvert::GENERIC; - - return s; -} - /// Uses the options to pick an SMT 2.0 solver /// \return An smt2_dect::solvert giving the solver to use. smt2_dect::solvert cbmc_solverst::get_smt2_solver_type() const @@ -189,76 +160,6 @@ std::unique_ptr cbmc_solverst::get_string_refinement() util_make_unique(info), std::move(prop)); } -std::unique_ptr cbmc_solverst::get_smt1( - smt1_dect::solvert solver) -{ - no_beautification(); - no_incremental_check(); - - const std::string &filename=options.get_option("outfile"); - - if(filename=="") - { - if(solver==smt1_dect::solvert::GENERIC) - { - error() << "please use --outfile" << eom; - throw 0; - } - - auto smt1_dec= - util_make_unique( - ns, - "cbmc", - "Generated by CBMC " CBMC_VERSION, - "QF_AUFBV", - solver); - - return util_make_unique(std::move(smt1_dec)); - } - else if(filename=="-") - { - auto smt1_conv= - util_make_unique( - ns, - "cbmc", - "Generated by CBMC " CBMC_VERSION, - "QF_AUFBV", - solver, - std::cout); - - smt1_conv->set_message_handler(get_message_handler()); - - return util_make_unique(std::move(smt1_conv)); - } - else - { - #ifdef _MSC_VER - auto out=util_make_unique(widen(filename)); - #else - auto out=util_make_unique(filename); - #endif - - if(!out) - { - error() << "failed to open " << filename << eom; - throw 0; - } - - auto smt1_conv= - util_make_unique( - ns, - "cbmc", - "Generated by CBMC " CBMC_VERSION, - "QF_AUFBV", - solver, - *out); - - smt1_conv->set_message_handler(get_message_handler()); - - return util_make_unique(std::move(smt1_conv), std::move(out)); - } -} - std::unique_ptr cbmc_solverst::get_smt2( smt2_dect::solvert solver) { diff --git a/src/cbmc/cbmc_solvers.h b/src/cbmc/cbmc_solvers.h index 2245ff59b70..66df55eca87 100644 --- a/src/cbmc/cbmc_solvers.h +++ b/src/cbmc/cbmc_solvers.h @@ -24,7 +24,6 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include -#include #include #include @@ -112,8 +111,6 @@ class cbmc_solverst:public messaget return get_bv_refinement(); else if(options.get_bool_option("refine-strings")) return get_string_refinement(); - if(options.get_bool_option("smt1")) - return get_smt1(get_smt1_solver_type()); if(options.get_bool_option("smt2")) return get_smt2(get_smt2_solver_type()); return get_default(); @@ -137,10 +134,8 @@ class cbmc_solverst:public messaget std::unique_ptr get_dimacs(); std::unique_ptr get_bv_refinement(); std::unique_ptr get_string_refinement(); - std::unique_ptr get_smt1(smt1_dect::solvert solver); std::unique_ptr get_smt2(smt2_dect::solvert solver); - smt1_dect::solvert get_smt1_solver_type() const; smt2_dect::solvert get_smt2_solver_type() const; // consistency checks during solver creation diff --git a/src/solvers/Makefile b/src/solvers/Makefile index 2256e0ee977..b33a2a149e1 100644 --- a/src/solvers/Makefile +++ b/src/solvers/Makefile @@ -189,8 +189,6 @@ SRC = $(BOOLEFORCE_SRC) \ sat/pbs_dimacs_cnf.cpp \ sat/resolution_proof.cpp \ sat/satcheck.cpp \ - smt1/smt1_conv.cpp \ - smt1/smt1_dec.cpp \ smt2/smt2_conv.cpp \ smt2/smt2_dec.cpp \ smt2/smt2_parser.cpp \ diff --git a/src/solvers/smt1/smt1_conv.cpp b/src/solvers/smt1/smt1_conv.cpp deleted file mode 100644 index 39c2e3f2e20..00000000000 --- a/src/solvers/smt1/smt1_conv.cpp +++ /dev/null @@ -1,3215 +0,0 @@ -/*******************************************************************\ - -Module: SMT Version 1 Backend - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -/// \file -/// SMT Version 1 Backend - -#include "smt1_conv.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -void smt1_convt::print_assignment(std::ostream &out) const -{ - // Boolean stuff - - for(std::size_t v=0; vsecond.value; - } - else if(expr.id()==ID_member) - { - const member_exprt &member_expr=to_member_expr(expr); - exprt tmp=get(member_expr.struct_op()); - if(tmp.is_nil()) - return nil_exprt(); - return member_exprt(tmp, member_expr.get_component_name(), expr.type()); - } - else if(expr.id()==ID_index) - { - const index_exprt &index_expr=to_index_expr(expr); - exprt tmp_array=get(index_expr.array()); - exprt tmp_index=get(index_expr.index()); - if(tmp_array.is_nil() || tmp_index.is_nil()) - return nil_exprt(); - return index_exprt(tmp_array, tmp_index, expr.type()); - } - else if(expr.id()==ID_constant) - return expr; - else if(expr.id()==ID_typecast) - { - exprt tmp=get(to_typecast_expr(expr).op()); - if(tmp.is_nil()) - return nil_exprt(); - return typecast_exprt(tmp, expr.type()); - } - - return nil_exprt(); -} - -exprt smt1_convt::ce_value( - const typet &type, - const std::string &index, - const std::string &value, - bool in_struct) const -{ - if(type.id()==ID_symbol) - return ce_value(ns.follow(type), index, value, in_struct); - - if(type.id()==ID_signedbv || - type.id()==ID_unsignedbv || - type.id()==ID_bv || - type.id()==ID_fixedbv) - { - assert(value.size()==boolbv_width(type)); - constant_exprt c(type); - c.set_value(value); - return c; - } - else if(type.id()==ID_bool) - { - if(value=="1") - return true_exprt(); - else if(value=="0") - return false_exprt(); - } - else if(type.id()==ID_pointer) - { - assert(value.size()==boolbv_width(type)); - - constant_exprt result(type); - result.set_value(value); - - // add the elaborated expression as operand - - pointer_logict::pointert p; - p.object=integer2unsigned( - binary2integer( - value.substr(0, config.bv_encoding.object_bits), false)); - - p.offset= - binary2integer( - value.substr(config.bv_encoding.object_bits, std::string::npos), true); - - result.copy_to_operands( - pointer_logic.pointer_expr(p, to_pointer_type(type))); - - return result; - } - else if(type.id()==ID_struct) - { - return binary2struct(to_struct_type(type), value); - } - else if(type.id()==ID_union) - { - return binary2union(to_union_type(type), value); - } - else if(type.id()==ID_array) - { - const array_typet &array_type = to_array_type(type); - const typet &subtype=ns.follow(type.subtype()); - - // arrays in structs are flat, no index - if(in_struct) - { - // we can only do fixed-size arrays - mp_integer size; - - if(!to_integer(array_type.size(), size)) - { - std::size_t size_int=integer2unsigned(size); - std::size_t sub_width=value.size()/size_int; - array_exprt array_list(array_type); - array_list.reserve_operands(size_int); - - std::size_t offset=value.size(); - - for(std::size_t i=0; i!=size_int; i++) - { - offset-=sub_width; - std::string sub_value=value.substr(offset, sub_width); - array_list.copy_to_operands(ce_value(subtype, "", sub_value, true)); - } - - return array_list; - } - } - else if(subtype.id()==ID_array) - { - // a 2 dimensional array - second dimension is flattened - return ce_value(subtype, "", value, true); - } - else - { - exprt value_expr=ce_value(subtype, "", value, in_struct); - - if(index=="") - return nil_exprt(); - - // use index, recusive call - exprt index_expr= - ce_value(signedbv_typet(index.size()), "", index, false); - - if(index_expr.is_nil()) - return nil_exprt(); - - array_list_exprt array_list(array_type); - array_list.copy_to_operands(index_expr, value_expr); - - return array_list; - } - } - - return nil_exprt(); -} - -typet smt1_convt::array_index_type() const -{ - return signedbv_typet(array_index_bits); -} - -void smt1_convt::array_index(const exprt &expr) -{ - if(expr.type().id()==ID_integer) - return convert_expr(expr, true); - - typet t=array_index_type(); - if(t==expr.type()) - return convert_expr(expr, true); - const typecast_exprt tmp(expr, t); - convert_expr(tmp, true); -} - -void smt1_convt::convert_address_of_rec( - const exprt &expr, - const pointer_typet &result_type) -{ - if(expr.id()==ID_symbol || - expr.id()==ID_constant || - expr.id()==ID_string_constant || - expr.id()==ID_label) - { - out - << "(concat" - << " bv" << pointer_logic.add_object(expr) << "[" - << config.bv_encoding.object_bits << "]" - << " bv0[" - << boolbv_width(result_type)-config.bv_encoding.object_bits << "]" - << ")"; - } - else if(expr.id()==ID_index) - { - if(expr.operands().size()!=2) - throw "index takes two operands"; - - const exprt &array=to_index_expr(expr).array(); - const exprt &index=to_index_expr(expr).index(); - - if(index.is_zero()) - { - if(array.type().id()==ID_pointer) - convert_expr(array, true); - else if(array.type().id()==ID_array) - convert_address_of_rec(array, result_type); - else - assert(false); - } - else - { - // this is really pointer arithmetic - exprt new_index_expr=expr; - new_index_expr.op1()=from_integer(0, index.type()); - - address_of_exprt address_of_expr( - new_index_expr, - pointer_type(array.type().subtype())); - - plus_exprt plus_expr( - address_of_expr, - index, - address_of_expr.type()); - - convert_expr(plus_expr, true); - } - } - else if(expr.id()==ID_member) - { - if(expr.operands().size()!=1) - throw "member takes one operand"; - - const member_exprt &member_expr=to_member_expr(expr); - - const exprt &struct_op=member_expr.struct_op(); - const typet &struct_op_type=ns.follow(struct_op.type()); - - if(struct_op_type.id()==ID_struct) - { - const struct_typet &struct_type= - to_struct_type(struct_op_type); - - const irep_idt &component_name= - member_expr.get_component_name(); - - mp_integer offset=member_offset(struct_type, component_name, ns); - assert(offset>=0); - - const unsignedbv_typet index_type(boolbv_width(result_type)); - - out << "(bvadd "; - convert_address_of_rec(struct_op, result_type); - out << " "; - convert_expr(from_integer(offset, index_type), true); - out << ")"; - } - else if(struct_op_type.id()==ID_union) - { - // these all have offset 0 - convert_address_of_rec(struct_op, result_type); - } - else - throw "unexpected type of member operand"; - } - else if(expr.id()==ID_if) - { - assert(expr.operands().size()==3); - - out << "(ite "; - convert_expr(expr.op0(), false); - out << " "; - convert_address_of_rec(expr.op1(), result_type); - out << " "; - convert_address_of_rec(expr.op2(), result_type); - out << ")"; - } - else - throw "don't know how to take address of: "+expr.id_string(); -} - -void smt1_convt::convert_byte_extract( - const byte_extract_exprt &expr, - bool bool_as_bv) -{ - // we just run the flattener - exprt flattened_expr=flatten_byte_extract(expr, ns); - convert_expr(flattened_expr, bool_as_bv); -} - -void smt1_convt::convert_byte_update( - const exprt &expr, - bool bool_as_bv) -{ - assert(expr.operands().size()==3); - - // The situation: expr.op0 needs to be split in 3 parts - // |<--- L --->|<--- M --->|<--- R --->| - // where M is the expr.op1'th byte - // We need to output L expr.op2 R - - mp_integer i; - if(to_integer(expr.op1(), i)) - throw "byte_update takes constant as second operand"; - - std::size_t w=boolbv_width(expr.op0().type()); - - if(w==0) - throw "failed to get width of byte_update operand"; - - mp_integer upper, lower; // of the byte - mp_integer max=w-1; - std::size_t op_w = boolbv_width(expr.op2().type()); - - if(expr.id()==ID_byte_update_little_endian) - { - lower = i*8; - upper = lower+op_w-1; - } - else - { - upper = max-(i*8); - lower = max-(i*8+op_w-1); - } - - if(upper==max) - { - if(lower==0) // there was only one byte - convert_expr(expr.op2(), true); - else // uppermost byte selected, only R needed - { - out << "(concat "; - convert_expr(expr.op2(), true); - out << " (extract[" << lower-1 << ":0] "; - convert_expr(expr.op0(), true); - out << ")"; // extract - out << ")"; // concat - } - } - else - { - if(lower==0) // lowermost byte selected, only L needed - { - out << "(concat "; - out << "(extract[" << max << ":" << (upper+1) << "] "; - convert_expr(expr.op0(), true); - out << ") "; - convert_expr(expr.op2(), true); - out << ")"; - } - else // byte in the middle selected, L & R needed - { - out << "(concat (concat"; - out << " (extract[" << max << ":" << (upper+1) << "] "; - convert_expr(expr.op0(), true); - out << ")"; // extract - out << " "; - convert_expr(expr.op2(), true); - out << ")"; // concat - out<< " (extract[" << (lower-1) << ":0] "; - convert_expr(expr.op0(), true); - out << ")"; // extract - out << ")"; // concat - } - } -} - -literalt smt1_convt::convert(const exprt &expr) -{ - assert(expr.type().id()==ID_bool); - - // Trivial cases that don't need a new handle. - - if(expr.is_true()) - return const_literal(true); - else if(expr.is_false()) - return const_literal(false); - else if(expr.id()==ID_literal) - return to_literal_expr(expr).get_literal(); - - // Ok, need new handle - - out << "\n"; - - find_symbols(expr); - - literalt l(no_boolean_variables, false); - no_boolean_variables++; - - out << ":extrapreds(("; - convert_literal(l); - out << "))" << "\n"; - - out << ":assumption ; convert " << "\n" - << " (iff "; - convert_literal(l); - out << " "; - convert_expr(expr, false); - out << ")" << "\n"; - - return l; -} - -std::string smt1_convt::convert_identifier(const irep_idt &identifier) -{ - std::string s=id2string(identifier), dest; - dest.reserve(s.size()); - - // a sequence of letters, digits, dots (.), single quotes (’), and - // underscores (_), starting with a letter - - // MathSAT does not really seem to like the single quotes ' - // so we avoid these. - - for(std::string::const_iterator - it=s.begin(); - it!=s.end(); - ++it) - { - char ch=*it; - - if(isalnum(ch) || ch=='_') - dest+=ch; - else if(ch==':') - { - std::string::const_iterator next_it(it); - ++next_it; - if(next_it!=s.end() && *next_it==':') - { - dest.append(".S"); - it=next_it; - } - else - dest+=".C"; - } - else if(ch=='#') - dest+=".H"; - else if(ch=='$') - dest+=".D"; - else if(ch=='!') - dest+=".E"; - else if(ch=='.') - dest+=".."; - else if(ch=='%') - dest+=".P"; - else - { - dest+='.'; - dest.append(std::to_string(ch)); - dest+='.'; - } - } - - return dest; -} - -void smt1_convt::convert_expr(const exprt &expr, bool bool_as_bv) -{ - if(expr.id()==ID_symbol) - { - const typet &type=expr.type(); - - irep_idt id=to_symbol_expr(expr).get_identifier(); - DATA_INVARIANT(!id.empty(), "symbol must have identifier"); - - // boolean symbols may have to be converted - from_bool_begin(type, bool_as_bv); - - out << convert_identifier(id); - - from_bool_end(type, bool_as_bv); - } - else if(expr.id()==ID_nondet_symbol) - { - const typet &type=expr.type(); - - irep_idt id=to_nondet_symbol_expr(expr).get_identifier(); - DATA_INVARIANT(!id.empty(), "symbol must have identifier"); - - // boolean symbols may have to be converted - from_bool_begin(type, bool_as_bv); - - out << "nondet_" << convert_identifier(id); - - from_bool_end(type, bool_as_bv); - } - else if(expr.id()==ID_literal) - { - convert_literal(to_literal_expr(expr).get_literal()); - } - else if(expr.id()==ID_typecast) - { - convert_typecast(to_typecast_expr(expr), bool_as_bv); - } - else if(expr.id()==ID_struct) - { - convert_struct(expr); - } - else if(expr.id()==ID_union) - { - convert_union(expr); - } - else if(expr.id()==ID_constant) - { - convert_constant(to_constant_expr(expr), bool_as_bv); - } - else if(expr.id()==ID_concatenation) - convert_nary(expr, "concat", true); - else if(expr.id()==ID_bitand) - convert_nary(expr, "bvand", true); - else if(expr.id()==ID_bitor) - convert_nary(expr, "bvor", true); - else if(expr.id()==ID_bitxor) - convert_nary(expr, "bvxor", true); - else if(expr.id()==ID_bitnand) - convert_nary(expr, "bvnand", true); - else if(expr.id()==ID_bitnor) - convert_nary(expr, "bvnor", true); - else if(expr.id()==ID_bitnot) - { - assert(expr.operands().size()==1); - out << "(bvnot "; - convert_expr(expr.op0(), true); - out << ")"; - } - else if(expr.id()==ID_unary_minus) - { - const typet &type=expr.type(); - - assert(expr.operands().size()==1); - - if(type.id()==ID_rational) - { - out << "(- "; - convert_expr(expr.op0(), true); - out << ")"; - } - else if(type.id()==ID_integer) - { - out << "(~ "; - convert_expr(expr.op0(), true); - out << ")"; - } - else - { - out << "(bvneg "; - convert_expr(expr.op0(), true); - out << ")"; - } - } - else if(expr.id()==ID_if) - { - assert(expr.operands().size()==3); - - // The SMTLIB standard requires a different operator in a boolean context - if(expr.op1().type().id()==ID_bool && !bool_as_bv) - out << "(if_then_else "; - else - out << "(ite "; - - convert_expr(expr.op0(), false); - out << " "; - convert_expr(expr.op1(), bool_as_bv); - out << " "; - convert_expr(expr.op2(), bool_as_bv); - out << ")"; - } - else if(expr.id()==ID_and || - expr.id()==ID_or || - expr.id()==ID_xor) - { - const typet &type=expr.type(); - const exprt::operandst &operands=expr.operands(); - - assert(type.id()==ID_bool); - assert(operands.size()>=2); - - // this may have to be converted - from_bool_begin(type, bool_as_bv); - - out << "(" << expr.id(); - forall_expr(it, operands) - { - out << " "; - convert_expr(*it, false); - } - out << ")"; - - // this may have to be converted - from_bool_end(type, bool_as_bv); - } - else if(expr.id()==ID_implies) - { - const typet &type=expr.type(); - - assert(type.id()==ID_bool); - assert(expr.operands().size()==2); - - // this may have to be converted - from_bool_begin(type, bool_as_bv); - - out << "(implies "; - convert_expr(expr.op0(), false); - out << " "; - convert_expr(expr.op1(), false); - out << ")"; - - // this may have to be converted - from_bool_end(type, bool_as_bv); - } - else if(expr.id()==ID_not) - { - const typet &type=expr.type(); - - assert(expr.operands().size()==1); - - // this may have to be converted - from_bool_begin(type, bool_as_bv); - - out << "(not "; - convert_expr(expr.op0(), false); - out << ")"; - - // this may have to be converted - from_bool_end(type, bool_as_bv); - } - else if(expr.id()==ID_equal || - expr.id()==ID_notequal) - { - const typet &type=expr.type(); - - assert(expr.operands().size()==2); - assert(base_type_eq(expr.op0().type(), expr.op1().type(), ns)); - - // this may have to be converted - from_bool_begin(type, bool_as_bv); - - if(expr.op0().type().id()==ID_bool) - { - if(expr.id()==ID_notequal) - out << "(xor "; - else - out << "(iff "; - - convert_expr(expr.op0(), false); - out << " "; - convert_expr(expr.op1(), false); - out << ")"; - } - else - { - if(expr.id()==ID_notequal) - { - out << "(not (= "; - convert_expr(expr.op0(), true); - out << " "; - convert_expr(expr.op1(), true); - out << "))"; - } - else - { - out << "(= "; - convert_expr(expr.op0(), true); - out << " "; - convert_expr(expr.op1(), true); - out << ")"; - } - } - - // this may have to be converted - from_bool_end(type, bool_as_bv); - } - else if(expr.id()==ID_le || - expr.id()==ID_lt || - expr.id()==ID_ge || - expr.id()==ID_gt) - { - convert_relation(expr, bool_as_bv); - } - else if(expr.id()==ID_plus) - { - convert_plus(to_plus_expr(expr)); - } - else if(expr.id()==ID_floatbv_plus) - { - convert_floatbv_plus(expr); - } - else if(expr.id()==ID_minus) - { - convert_minus(to_minus_expr(expr)); - } - else if(expr.id()==ID_floatbv_minus) - { - convert_floatbv_minus(expr); - } - else if(expr.id()==ID_div) - { - convert_div(to_div_expr(expr)); - } - else if(expr.id()==ID_floatbv_div) - { - convert_floatbv_div(expr); - } - else if(expr.id()==ID_mod) - { - convert_mod(to_mod_expr(expr)); - } - else if(expr.id()==ID_mult) - { - convert_mult(to_mult_expr(expr)); - } - else if(expr.id()==ID_floatbv_mult) - { - convert_floatbv_mult(expr); - } - else if(expr.id()==ID_address_of) - { - const typet &type=expr.type(); - - assert(expr.operands().size()==1); - assert(type.id()==ID_pointer); - convert_address_of_rec(expr.op0(), to_pointer_type(type)); - } - else if(expr.id()=="implicit_address_of" || - expr.id()=="reference_to") - { - // old stuff - assert(false); - } - else if(expr.id()==ID_array_of) - { - assert(expr.type().id()==ID_array); - assert(expr.operands().size()==1); - - // const array_typet &array_type=to_array_type(expr.type()); - - // not really there in SMT, so we replace it - // this is an over-approximation - array_of_mapt::const_iterator it=array_of_map.find(expr); - assert(it!=array_of_map.end()); - - out << it->second; - } - else if(expr.id()==ID_index) - { - convert_index(to_index_expr(expr), bool_as_bv); - } - else if(expr.id()==ID_ashr || - expr.id()==ID_lshr || - expr.id()==ID_shl) - { - const typet &type=expr.type(); - - assert(expr.operands().size()==2); - - if(type.id()==ID_unsignedbv || - type.id()==ID_signedbv || - type.id()==ID_bv || - type.id()==ID_struct || - type.id()==ID_union) - { - if(expr.id()==ID_ashr) - out << "(bvashr "; - else if(expr.id()==ID_lshr) - out << "(bvlshr "; - else if(expr.id()==ID_shl) - out << "(bvshl "; - else - assert(false); - - convert_expr(expr.op0(), true); - out << " "; - - // SMT1 requires the shift distance to have the same width as - // the value that is shifted -- odd! - - std::size_t width_op0=boolbv_width(expr.op0().type()); - std::size_t width_op1=boolbv_width(expr.op1().type()); - - if(width_op0==width_op1) - convert_expr(expr.op1(), true); - else if(width_op0>width_op1) - { - out << "(zero_extend[" << width_op0-width_op1 << "] "; - convert_expr(expr.op1(), true); - out << ")"; // zero_extend - } - else // width_op00) - out << "(zero_extend[" << ext << "] "; - - out << "(extract[" - << (op_width-1) - << ":" - << op_width-1-config.bv_encoding.object_bits << "] "; - convert_expr(expr.op0(), true); - out << ")"; - - if(ext>0) - out << ")"; - } - else if(expr.id()=="is_dynamic_object") - { - convert_is_dynamic_object(expr, bool_as_bv); - } - else if(expr.id()==ID_invalid_pointer) - { - const typet &type=expr.type(); - - assert(expr.operands().size()==1); - assert(expr.op0().type().id()==ID_pointer); - std::size_t op_width=boolbv_width(expr.op0().type()); - - // this may have to be converted - from_bool_begin(type, bool_as_bv); - - out << "(= (extract[" - << (op_width-1) - << ":" << op_width-config.bv_encoding.object_bits << "] "; - convert_expr(expr.op0(), true); - out << ") bv" << pointer_logic.get_invalid_object() - << "[" << config.bv_encoding.object_bits << "])"; - - // this may have to be converted - from_bool_end(type, bool_as_bv); - } - else if(expr.id()=="pointer_object_has_type") - { - const typet &type=expr.type(); - - assert(expr.operands().size()==1); - - // this may have to be converted - from_bool_begin(type, bool_as_bv); - - out << "false"; // TODO - - // this may have to be converted - from_bool_end(type, bool_as_bv); - } - else if(expr.id()==ID_string_constant) - { - exprt tmp; - string2array_mapt::const_iterator fit=string2array_map.find(expr); - assert(fit!=string2array_map.end()); - - convert_expr(fit->second, true); - } - else if(expr.id()==ID_extractbit) - { - assert(expr.operands().size()==2); - - if(expr.op0().type().id()==ID_unsignedbv || - expr.op0().type().id()==ID_signedbv) - { - const typet &type=expr.type(); - - // this may have to be converted - from_bv_begin(type, bool_as_bv); - - if(expr.op1().is_constant()) - { - mp_integer i; - if(to_integer(expr.op1(), i)) - throw "extractbit: to_integer failed"; - - out << "(extract[" << i << ":" << i << "] "; - convert_expr(expr.op0(), true); - out << ")"; - } - else - { - out << "(extract[0:0] "; - // the arguments of the shift need to have the same width - out << "(bvlshr "; - convert_expr(expr.op0(), true); - typecast_exprt tmp(expr.op0().type()); - tmp.op0()=expr.op1(); - convert_expr(tmp, true); - out << "))"; // bvlshr, extract - } - - // this may have to be converted - from_bv_end(type, bool_as_bv); - } - else - throw "unsupported type for "+expr.id_string()+ - ": "+expr.op0().type().id_string(); - } - else if(expr.id()==ID_replication) - { - assert(expr.operands().size()==2); - - mp_integer times; - if(to_integer(expr.op0(), times)) - throw "replication takes constant as first parameter"; - - out << "(repeat[" << times << "] "; - convert_expr(expr.op1(), true); // this ensures we have a vector - out << ")"; - } - else if(expr.id()==ID_byte_extract_little_endian || - expr.id()==ID_byte_extract_big_endian) - { - convert_byte_extract(to_byte_extract_expr(expr), bool_as_bv); - } - else if(expr.id()==ID_byte_update_little_endian || - expr.id()==ID_byte_update_big_endian) - { - convert_byte_update(expr, bool_as_bv); - } - else if(expr.id()==ID_width) - { - std::size_t result_width=boolbv_width(expr.type()); - - if(result_width==0) - throw "conversion failed"; - - if(expr.operands().size()!=1) - throw "width expects 1 operand"; - - std::size_t op_width=boolbv_width(expr.op0().type()); - - if(op_width==0) - throw "conversion failed"; - - out << "bv" << op_width/8 << "[" << result_width << "]"; - } - else if(expr.id()==ID_abs) - { - const typet &type=expr.type(); - - assert(expr.operands().size()==1); - const exprt &op0=expr.op0(); - - std::size_t result_width=boolbv_width(type); - - if(result_width==0) - throw "conversion failed"; - - if(type.id()==ID_signedbv || - type.id()==ID_fixedbv) - { - out << "(ite (bvslt "; - convert_expr(op0, true); - out << " bv0[" << result_width << "]) "; - out << "(bvneg "; - convert_expr(op0, true); - out << ") "; - convert_expr(op0, true); - out << ")"; - } - else if(type.id()==ID_floatbv) - { - out << "(bvand "; - convert_expr(op0, true); - out << " bv" - << (power(2, result_width-1)-1) - << "[" << result_width << "])"; - } - else - throw "abs with unsupported operand type"; - } - else if(expr.id()==ID_isnan) - { - const typet &type=expr.type(); - - assert(expr.operands().size()==1); - - const typet &op_type=expr.op0().type(); - - if(op_type.id()==ID_fixedbv) - { - from_bool_begin(type, bool_as_bv); - out << "false"; - from_bool_end(type, bool_as_bv); - } - else - throw "isnan with unsupported operand type"; - } - else if(expr.id()==ID_isfinite) - { - const typet &type=expr.type(); - - if(expr.operands().size()!=1) - throw "isfinite expects one operand"; - - const typet &op_type=expr.op0().type(); - - if(op_type.id()==ID_fixedbv) - { - from_bool_begin(type, bool_as_bv); - out << "true"; - from_bool_end(type, bool_as_bv); - } - else - throw "isfinite with unsupported operand type"; - } - else if(expr.id()==ID_isinf) - { - const typet &type=expr.type(); - - if(expr.operands().size()!=1) - throw "isinf expects one operand"; - - const typet &op_type=expr.op0().type(); - - if(op_type.id()==ID_fixedbv) - { - from_bool_begin(type, bool_as_bv); - out << "false"; - from_bool_end(type, bool_as_bv); - } - else - throw "isinf with unsupported operand type"; - } - else if(expr.id()==ID_isnormal) - { - const typet &type=expr.type(); - - if(expr.operands().size()!=1) - throw "isnormal expects one operand"; - - const typet &op_type=expr.op0().type(); - - if(op_type.id()==ID_fixedbv) - { - from_bool_begin(type, bool_as_bv); - out << "true"; - from_bool_end(type, bool_as_bv); - } - else - throw "isnormal with unsupported operand type"; - } - else if(expr.id()==ID_overflow_plus || - expr.id()==ID_overflow_minus) - { - const typet &type=expr.type(); - - assert(expr.operands().size()==2); - bool subtract=expr.id()==ID_overflow_minus; - - const typet &op_type=expr.op0().type(); - - std::size_t width=boolbv_width(op_type); - - if(op_type.id()==ID_signedbv) - { - // an overflow occurs if the top two bits of the extended sum differ - - from_bool_begin(type, bool_as_bv); - out << "(let (?sum ("; - out << (subtract?"bvsub":"bvadd"); - out << " (sign_extend[1] "; - convert_expr(expr.op0(), true); - out << ")"; - out << " (sign_extend[1] "; - convert_expr(expr.op1(), true); - out << "))) "; // sign_extend, bvadd/sub let2 - out << "(not (= " - "(extract[" << width << ":" << width << "] ?sum) " - "(extract[" << (width-1) << ":" << (width-1) << "] ?sum)"; - out << ")))"; // =, not, let - from_bool_end(type, bool_as_bv); - } - else if(op_type.id()==ID_unsignedbv) - { - // overflow is simply carry-out - from_bv_begin(type, bool_as_bv); - out << "(extract[" << width << ":" << width << "] "; - out << "(" << (subtract?"bvsub":"bvadd"); - out << " (zero_extend[1] "; - convert_expr(expr.op0(), true); - out << ")"; - out << " (zero_extend[1] "; - convert_expr(expr.op1(), true); - out << ")))"; // zero_extend, bvsub/bvadd, extract - from_bv_end(type, bool_as_bv); - } - else - throw "overflow check on unknown type: "+op_type.id_string(); - } - else if(expr.id()==ID_overflow_mult) - { - assert(expr.operands().size()==2); - - // No better idea than to multiply with double the bits and then compare - // with max value. - - const typet &op_type=expr.op0().type(); - std::size_t width=boolbv_width(op_type); - - if(op_type.id()==ID_signedbv) - { - out << "(let (?prod (bvmul (sign_extend[" << width << "] "; - convert_expr(expr.op0(), true); - out << ") (sign_extend[" << width << "] "; - convert_expr(expr.op1(), true); - out << "))) "; // sign_extend, bvmul, ?prod - out << "(or (bvsge ?prod (bv" << power(2, width-1) - << "[" << width*2 << "]))"; - out << " (bvslt ?prod (bvneg (bv" << power(2, width-1) - << "[" << width*2 << "])))"; - out << "))"; // or, let - } - else if(op_type.id()==ID_unsignedbv) - { - out << "(bvuge (bvmul (zero_extend[" << width << "] "; - convert_expr(expr.op0(), true); - out << ") (zero_extend[" << width << "] "; - convert_expr(expr.op1(), true); - out << ")) bv" << power(2, width) << "[" << width*2 << "])"; - } - else - throw "overflow-* check on unknown type: "+op_type.id_string(); - } - else if(expr.id()==ID_forall || expr.id()==ID_exists) - { - from_bv_begin(expr.type(), bool_as_bv); - - assert(expr.operands().size()==2); - out << "(" << expr.id() << " ("; - exprt bound=expr.op0(); - convert_expr(bound, false); - out << " "; - - if(bound.type().id()==ID_bool) - out << "Bool"; - else - convert_type(bound.type()); - - out << ") "; - convert_expr(expr.op1(), false); - out << ")"; - - from_bv_end(expr.type(), bool_as_bv); - } - else if(expr.id()==ID_extractbits) - { - assert(expr.operands().size()==3); - - const typet &op_type=ns.follow(expr.op0().type()); - - if(op_type.id()==ID_unsignedbv || - op_type.id()==ID_signedbv || - op_type.id()==ID_bv || - op_type.id()==ID_fixedbv || - op_type.id()==ID_struct || - op_type.id()==ID_union || - op_type.id()==ID_vector) - { - if(expr.op1().is_constant() && - expr.op2().is_constant()) - { - mp_integer op1_i, op2_i; - - if(to_integer(expr.op1(), op1_i)) - throw "extractbits: to_integer failed"; - - if(to_integer(expr.op2(), op2_i)) - throw "extractbits: to_integer failed"; - - out << "(extract[" << op1_i << ":" << op2_i << "] "; - convert_expr(expr.op0(), true); - out << ")"; - } - else - { - #if 0 - out << "(extract["; - convert_expr(expr.op1(), bool_as_bv); - out << ":"; - convert_expr(expr.op2(), bool_as_bv); - out << "] "; - convert_expr(expr.op0(), bool_as_bv); - out << ")"; - #endif - throw "smt1 todo: extractbits with variable bits"; - } - } - else - throw "unsupported type for "+expr.id_string()+ - ": "+op_type.id_string(); - } - else if(expr.id()==ID_array) - { - const exprt::operandst &operands=expr.operands(); - - // array constructor - array_expr_mapt::const_iterator it=array_expr_map.find(expr); - assert(it!=array_expr_map.end()); - - assert(!operands.empty()); - - forall_expr(it, operands) - out << "(store "; - - out << it->second; - - std::size_t i=0; - forall_expr(it, operands) - { - exprt index=from_integer(i, unsignedbv_typet(array_index_bits)); - out << " "; - convert_expr(index, true); - out << " "; - convert_expr(*it, true); - out << ")"; - i++; - } - } - else if(expr.id()==ID_vector) - { - // Vector constructor. - // We flatten the vector by concatenating its elements. - convert_nary(expr, "concat", bool_as_bv); - } - else - throw "smt1_convt::convert_expr: `"+ - expr.id_string()+"' is unsupported"; -} - -void smt1_convt::convert_typecast( - const typecast_exprt &expr, - bool bool_as_bv) -{ - assert(expr.operands().size()==1); - const exprt &src=expr.op0(); - - typet dest_type=ns.follow(expr.type()); - if(dest_type.id()==ID_c_enum_tag) - dest_type=ns.follow_tag(to_c_enum_tag_type(dest_type)); - - typet src_type=ns.follow(src.type()); - if(src_type.id()==ID_c_enum_tag) - src_type=ns.follow_tag(to_c_enum_tag_type(src_type)); - - if(dest_type.id()==ID_bool) - { - // boolean typecasts may have to be converted - from_bool_begin(dest_type, bool_as_bv); - - // this is comparison with zero - if(src_type.id()==ID_signedbv || - src_type.id()==ID_unsignedbv || - src_type.id()==ID_fixedbv || - src_type.id()==ID_c_bit_field || - src_type.id()==ID_pointer) - { - out << "(not (= "; - convert_expr(src, true); - out << " "; - convert_expr( - from_integer(0, src_type), - true); - out << "))"; - } - else - { - // NOLINTNEXTLINE(readability/throw) - throw "TODO typecast1 "+src_type.id_string()+" -> bool"; - } - - // boolean typecasts may have to be converted - from_bool_end(dest_type, bool_as_bv); - } - else if(dest_type.id()==ID_c_bool) - { - // this is comparison with zero - if(src_type.id()==ID_signedbv || - src_type.id()==ID_unsignedbv || - src_type.id()==ID_fixedbv || - src_type.id()==ID_c_bit_field || - src_type.id()==ID_pointer) - { - std::size_t to_width=boolbv_width(dest_type); - - out << "(ite "; - out << "(not (= "; - convert_expr(src, true); - out << " "; - convert_expr( - from_integer(0, src_type), - true); - out << ")) "; // not, = - out << " bv1[" << to_width << "]"; - out << " bv0[" << to_width << "]"; - out << ")"; // ite - } - else - { - // NOLINTNEXTLINE(readability/throw) - throw "TODO typecast1 "+src_type.id_string()+" -> bool"; - } - } - else if(dest_type.id()==ID_signedbv || - dest_type.id()==ID_unsignedbv || - dest_type.id()==ID_c_enum) - { - std::size_t to_width=boolbv_width(dest_type); - - if(src_type.id()==ID_signedbv || // from signedbv - src_type.id()==ID_unsignedbv || // from unsigedbv - src_type.id()==ID_c_bool || - src_type.id()==ID_c_enum) - { - std::size_t from_width=boolbv_width(src_type); - - if(from_width==to_width) - convert_expr(src, true); // ignore - else if(from_widthfrom_integer_bits) - { - out << "(sign_extend[" << (to_width-from_integer_bits) << "] "; - out << "(extract[" << (from_width-1) << ":" - << from_fraction_bits << "] "; - convert_expr(src, true); - out << "))"; - } - else - { - out << "(extract[" << (from_fraction_bits+to_width-1) - << ":" << from_fraction_bits << "] "; - convert_expr(src, true); - out << ")"; - } - } - else if(src_type.id()==ID_bool) // from boolean - { - out << "(ite "; - convert_expr(src, false); - - if(dest_type.id()==ID_fixedbv) - { - fixedbv_spect spec(to_fixedbv_type(expr.type())); - out << " (concat bv1[" << spec.integer_bits << "] " << - "bv0[" << spec.get_fraction_bits() << "]) " << - "bv0[" << spec.width << "]"; - } - else - { - out << " bv1[" << to_width << "]"; - out << " bv0[" << to_width << "]"; - } - - out << ")"; - } - else if(src_type.id()==ID_pointer) // from pointer to int - { - std::size_t from_width=boolbv_width(src_type); - - if(from_width "+dest_type.id_string(); - } - } - else if(dest_type.id()==ID_fixedbv) // to fixedbv - { - const fixedbv_typet &fixedbv_type=to_fixedbv_type(dest_type); - std::size_t to_fraction_bits=fixedbv_type.get_fraction_bits(); - std::size_t to_integer_bits=fixedbv_type.get_integer_bits(); - - if(src_type.id()==ID_unsignedbv || - src_type.id()==ID_signedbv || - src_type.id()==ID_c_enum) - { - // integer to fixedbv - std::size_t from_width=to_bitvector_type(src_type).get_width(); - - // we just concatenate a zero-valued fractional part - out << "(concat"; - - if(from_width==to_integer_bits) - convert_expr(src, true); - else if(from_width>to_integer_bits) - { - // too many integer bits, chop some off - out << " (extract[" << (to_integer_bits-1) << ":0] "; - convert_expr(src, true); - out << ")"; - } - else - { - // too few integer bits - assert(from_widthfrom_integer_bits); - out << "(sign_extend[" - << (to_integer_bits-from_integer_bits) - << "] (extract[" - << (from_width-1) << ":" - << from_fraction_bits - << "] "; - convert_expr(src, true); - out << "))"; - } - - out << " "; - - if(to_fraction_bits<=from_fraction_bits) - { - out << "(extract[" - << (from_fraction_bits-1) << ":" - << (from_fraction_bits-to_fraction_bits) - << "] "; - convert_expr(src, true); - out << ")"; - } - else - { - assert(to_fraction_bits>from_fraction_bits); - out << "(concat (extract[" - << (from_fraction_bits-1) << ":0] "; - convert_expr(src, true); - out << ")" - << " bv0[" << to_fraction_bits-from_fraction_bits - << "])"; - } - - out << ")"; // concat - } - else - throw "unexpected typecast to fixedbv"; - } - else if(dest_type.id()==ID_pointer) - { - std::size_t to_width=boolbv_width(dest_type); - - if(src_type.id()==ID_pointer) - { - // this just passes through - convert_expr(src, true); - } - else if(src_type.id()==ID_unsignedbv || - src_type.id()==ID_signedbv) - { - std::size_t from_width=boolbv_width(src_type); - - if(from_width==to_width) - convert_expr(src, true); // pass through - else if(from_widthto_width - { - out << "(extract[" - << to_width - << ":0] "; - convert_expr(src, true); - out << ")"; // extract - } - } - else - // NOLINTNEXTLINE(readability/throw) - throw "TODO typecast3 "+src_type.id_string()+" -> pointer"; - } - else if(dest_type.id()==ID_range) - { - // NOLINTNEXTLINE(readability/throw) - throw "TODO range typecast"; - } - else if(dest_type.id()==ID_c_bit_field) - { - std::size_t from_width=boolbv_width(src_type); - std::size_t to_width=boolbv_width(dest_type); - - if(from_width==to_width) - convert_expr(src, bool_as_bv); // ignore - else - { - typet t=c_bit_field_replacement_type(to_c_bit_field_type(dest_type), ns); - typecast_exprt tmp(typecast_exprt(src, t), dest_type); - convert_typecast(tmp, bool_as_bv); - } - } - else - // NOLINTNEXTLINE(readability/throw) - throw "TODO typecast4 ? -> "+dest_type.id_string(); -} - -void smt1_convt::convert_struct(const exprt &expr) -{ - const struct_typet &struct_type=to_struct_type(expr.type()); - - const struct_typet::componentst &components= - struct_type.components(); - - assert(components.size()==expr.operands().size()); - - assert(!components.empty()); - - if(components.size()==1) - { - const exprt &op=expr.op0(); - - if(op.type().id()==ID_array) - flatten_array(op); - else - convert_expr(op, true); - } - else - { - std::size_t nr_ops=0; - - for(std::size_t i=0; imember_width); - out << "(concat "; - out << "bv0[" << (total_width-member_width) << "] "; - convert_expr(op, true); - out << ")"; - } -} - -void smt1_convt::convert_constant( - const constant_exprt &expr, - bool bool_as_bv) -{ - if(expr.type().id()==ID_unsignedbv || - expr.type().id()==ID_signedbv || - expr.type().id()==ID_bv || - expr.type().id()==ID_c_enum || - expr.type().id()==ID_c_enum_tag || - expr.type().id()==ID_c_bool || - expr.type().id()==ID_c_bit_field) - { - mp_integer value; - - if(to_integer(expr, value)) - throw "failed to convert bitvector constant"; - - std::size_t width=boolbv_width(expr.type()); - - if(value<0) - value=power(2, width)+value; - - out << "bv" << value - << "[" << width << "]"; - } - else if(expr.type().id()==ID_fixedbv) - { - fixedbv_spect spec(to_fixedbv_type(expr.type())); - - std::string v_str=expr.get_string(ID_value); - mp_integer v=binary2integer(v_str, false); - - out << "bv" << v << "[" << spec.width << "]"; - } - else if(expr.type().id()==ID_floatbv) - { - ieee_float_spect spec(to_floatbv_type(expr.type())); - - std::string v_str=expr.get_string(ID_value); - mp_integer v=binary2integer(v_str, false); - - out << "bv" << v << "[" << spec.width() << "]"; - } - else if(expr.type().id()==ID_pointer) - { - const irep_idt &value=expr.get(ID_value); - - if(value==ID_NULL) - { - assert(boolbv_width(expr.type())!=0); - out << "(concat" - << " bv" << pointer_logic.get_null_object() - << "[" << config.bv_encoding.object_bits << "]" - << " bv0[" << boolbv_width(expr.type())-config.bv_encoding.object_bits - << "]" - << ")"; // concat - } - else - throw "unknown pointer constant: "+id2string(value); - } - else if(expr.type().id()==ID_bool) - { - if(expr.is_true()) - out << (bool_as_bv?"bit1":"true"); - else if(expr.is_false()) - out << (bool_as_bv?"bit0":"false"); - else - throw "unknown boolean constant"; - } - else if(expr.type().id()==ID_array) - { - // this should be the 'array' expression - assert(false); - } - else if(expr.type().id()==ID_rational) - { - std::string value=expr.get_string(ID_value); - size_t pos=value.find("/"); - - if(pos==std::string::npos) - out << value << ".0"; - else - { - out << "(/ " << value.substr(0, pos) << ".0 " - << value.substr(pos+1) << ".0)"; - } - } - else if(expr.type().id()==ID_integer || - expr.type().id()==ID_natural) - { - std::string value=expr.get_string(ID_value); - - if(value[0]=='-') - out << "(~ " << value.substr(1) << ")"; - else - out << value; - } - else - throw "unknown constant: "+expr.type().id_string(); -} - -void smt1_convt::convert_mod(const mod_exprt &expr) -{ - assert(expr.operands().size()==2); - - if(expr.type().id()==ID_unsignedbv || - expr.type().id()==ID_signedbv) - { - if(expr.type().id()==ID_unsignedbv) - out << "(bvurem "; - else - out << "(bvsrem "; - - convert_expr(expr.op0(), true); - out << " "; - convert_expr(expr.op1(), true); - out << ")"; - } - else - throw "unsupported type for mod: "+expr.type().id_string(); -} - -void smt1_convt::convert_is_dynamic_object( - const exprt &expr, - bool bool_as_bv) -{ - std::vector dynamic_objects; - pointer_logic.get_dynamic_objects(dynamic_objects); - - assert(expr.operands().size()==1); - assert(expr.op0().type().id()==ID_pointer); - std::size_t op_width=boolbv_width(expr.op0().type()); - - // this may have to be converted - from_bool_begin(expr.type(), bool_as_bv); - - if(dynamic_objects.empty()) - out << "false"; - else - { - // let is only allowed in formulas - - out << "(let (?obj (extract[" - << (op_width-1) - << ":" << op_width-config.bv_encoding.object_bits << "] "; - convert_expr(expr.op0(), true); - out << ")) "; - - if(dynamic_objects.size()==1) - { - out << "(= bv" << dynamic_objects.front() - << "[" << config.bv_encoding.object_bits << "] ?obj)"; - } - else - { - out << "(or"; - - for(const auto &obj : dynamic_objects) - out << " (= bv" << obj - << "[" << config.bv_encoding.object_bits << "] ?obj)"; - - out << ")"; // or - } - - out << ")"; // let - } - - // this may have to be converted - from_bool_end(expr.type(), bool_as_bv); -} - -void smt1_convt::convert_relation(const exprt &expr, bool bool_as_bv) -{ - assert(expr.operands().size()==2); - - // this may have to be converted - from_bool_begin(expr.type(), bool_as_bv); - - const typet &op_type=expr.op0().type(); - - out << "("; - - if(op_type.id()==ID_unsignedbv || - op_type.id()==ID_pointer) - { - if(expr.id()==ID_le) - out << "bvule"; - else if(expr.id()==ID_lt) - out << "bvult"; - else if(expr.id()==ID_ge) - out << "bvuge"; - else if(expr.id()==ID_gt) - out << "bvugt"; - - out << " "; - convert_expr(expr.op0(), true); - out << " "; - convert_expr(expr.op1(), true); - } - else if(op_type.id()==ID_signedbv || - op_type.id()==ID_fixedbv) - { - if(expr.id()==ID_le) - out << "bvsle"; - else if(expr.id()==ID_lt) - out << "bvslt"; - else if(expr.id()==ID_ge) - out << "bvsge"; - else if(expr.id()==ID_gt) - out << "bvsgt"; - - out << " "; - convert_expr(expr.op0(), true); - out << " "; - convert_expr(expr.op1(), true); - } - else if(op_type.id()==ID_rational || - op_type.id()==ID_integer) - { - out << expr.id(); - - out << " "; - convert_expr(expr.op0(), true); - out << " "; - convert_expr(expr.op1(), true); - } - else - throw "unsupported type for "+expr.id_string()+ - ": "+op_type.id_string(); - - out << ")"; - - // this may have to be converted - from_bool_end(expr.type(), bool_as_bv); -} - -void smt1_convt::convert_plus(const plus_exprt &expr) -{ - assert(expr.operands().size()>=2); - - if(expr.type().id()==ID_unsignedbv || - expr.type().id()==ID_signedbv || - expr.type().id()==ID_fixedbv) - { - convert_nary(expr, "bvadd", true); - } - else if(expr.type().id()==ID_pointer) - { - if(expr.operands().size()<2) - throw "pointer arithmetic with less than two operands"; - - if(expr.operands().size()==2) - { - exprt p=expr.op0(), i=expr.op1(); - - if(p.type().id()!=ID_pointer) - p.swap(i); - - if(p.type().id()!=ID_pointer) - throw "unexpected mixture in pointer arithmetic"; - - mp_integer element_size= - pointer_offset_size(expr.type().subtype(), ns); - assert(element_size>0); - - // adjust width if needed - if(boolbv_width(i.type())!=boolbv_width(expr.type())) - i.make_typecast(signedbv_typet(boolbv_width(expr.type()))); - - out << "(bvadd "; - convert_expr(p, true); - out << " "; - - if(element_size>=2) - { - out << "(bvmul "; - convert_expr(i, true); - out << " bv" << element_size - << "[" << boolbv_width(expr.type()) << "])"; - } - else - convert_expr(i, true); - - out << ")"; - } - else - { - // more than two operands - exprt p; - typet integer_type=signedbv_typet(boolbv_width(expr.type())); - exprt integer_sum(ID_plus, integer_type); - - forall_operands(it, expr) - { - if(it->type().id()==ID_pointer) - p=*it; - else - integer_sum.copy_to_operands(*it); - } - - Forall_operands(it, integer_sum) - if(it->type()!=integer_type) - it->make_typecast(integer_type); - - plus_exprt pointer_arithmetic(p, integer_sum, expr.type()); - convert_plus(pointer_arithmetic); // recursive call - } - } - else if(expr.type().id()==ID_rational || - expr.type().id()==ID_integer) - { - convert_nary(expr, "+", true); - } - else - throw "unsupported type for +: "+expr.type().id_string(); -} - -void smt1_convt::convert_floatbv_plus(const exprt &expr) -{ - assert(expr.operands().size()==3); - assert(expr.type().id()==ID_floatbv); - - throw "todo: floatbv_plus"; -} - -void smt1_convt::convert_minus(const minus_exprt &expr) -{ - assert(expr.operands().size()==2); - - if(expr.type().id()==ID_unsignedbv || - expr.type().id()==ID_signedbv || - expr.type().id()==ID_fixedbv) - { - out << "(bvsub "; - - if(expr.op0().type().id()==ID_pointer) - out << "(extract[" << boolbv_width(expr.op0().type())-1 << ":0] "; - convert_expr(expr.op0(), true); - if(expr.op0().type().id()==ID_pointer) - out << ")"; - - out << " "; - - if(expr.op1().type().id()==ID_pointer) - out << "(extract[" << boolbv_width(expr.op1().type())-1 << ":0] "; - convert_expr(expr.op1(), true); - if(expr.op1().type().id()==ID_pointer) - out << ")"; - - out << ")"; - } - else if(expr.type().id()==ID_pointer) - { - convert_expr(binary_exprt( - expr.op0(), - "+", - unary_minus_exprt(expr.op1(), expr.op1().type()), - expr.type()), - true); - } - else - throw "unsupported type for -: "+expr.type().id_string(); -} - -void smt1_convt::convert_floatbv_minus(const exprt &expr) -{ - assert(expr.operands().size()==3); - assert(expr.type().id()==ID_floatbv); - - throw "todo: floatbv_minus"; -} - -void smt1_convt::convert_div(const div_exprt &expr) -{ - assert(expr.operands().size()==2); - - if(expr.type().id()==ID_unsignedbv || - expr.type().id()==ID_signedbv) - { - if(expr.type().id()==ID_unsignedbv) - out << "(bvudiv "; - else - out << "(bvsdiv "; - - convert_expr(expr.op0(), true); - out << " "; - convert_expr(expr.op1(), true); - out << ")"; - } - else if(expr.type().id()==ID_fixedbv) - { - fixedbv_spect spec(to_fixedbv_type(expr.type())); - std::size_t fraction_bits=spec.get_fraction_bits(); - - out << "(extract[" << spec.width-1 << ":0] "; - out << "(bvsdiv "; - - out << "(concat "; - convert_expr(expr.op0(), true); - out << " bv0[" << fraction_bits << "]) "; - - out << "(sign_extend[" << fraction_bits << "] "; - convert_expr(expr.op1(), true); - out << ")"; - - out << "))"; - } - else - throw "unsupported type for /: "+expr.type().id_string(); -} - -void smt1_convt::convert_floatbv_div(const exprt &expr) -{ - assert(expr.operands().size()==3); - assert(expr.type().id()==ID_floatbv); - - throw "todo: floatbv_div"; -} - -void smt1_convt::convert_mult(const mult_exprt &expr) -{ - assert(expr.operands().size()>=2); - - // re-write to binary if needed - if(expr.operands().size()>2) - { - // strip last operand - exprt tmp=expr; - tmp.operands().pop_back(); - - // recursive call - return convert_mult(mult_exprt(tmp, expr.operands().back())); - } - - assert(expr.operands().size()==2); - - if(expr.type().id()==ID_unsignedbv || - expr.type().id()==ID_signedbv) - { - // Note that bvmul is really unsigned, - // but this is irrelevant as we chop-off any extra result - // bits. - out << "(bvmul "; - convert_expr(expr.op0(), true); - out << " "; - convert_expr(expr.op1(), true); - out << ")"; - } - else if(expr.type().id()==ID_fixedbv) - { - fixedbv_spect spec(to_fixedbv_type(expr.type())); - std::size_t fraction_bits=spec.get_fraction_bits(); - - // strip away faction_bits off the result - out << "(extract[" << spec.width+fraction_bits-1 << ":" - << fraction_bits << "] "; - - out << "(bvmul "; - - out << "(sign_extend[" << fraction_bits << "] "; - convert_expr(expr.op0(), true); - out << ") "; - - out << "(sign_extend[" << fraction_bits << "] "; - convert_expr(expr.op1(), true); - out << ") "; - - out << ")"; // bvmul, fraction_bits+width wide - out << ")"; // extract, width bits wide - } - else if(expr.type().id()==ID_rational) - { - out << "(* "; - convert_expr(expr.op0(), true); - out << " "; - convert_expr(expr.op1(), true); - out << ")"; - } - else - throw "unsupported type for *: "+expr.type().id_string(); -} - -void smt1_convt::convert_floatbv_mult(const exprt &expr) -{ - assert(expr.operands().size()==3); - assert(expr.type().id()==ID_floatbv); - - throw "todo: floatbv_mult"; -} - -void smt1_convt::convert_with(const exprt &expr) -{ - // get rid of "with" that has more than three operands - - assert(expr.operands().size()>=3); - - if(expr.operands().size()>3) - { - std::size_t s=expr.operands().size(); - - // strip of the trailing two operands - exprt tmp=expr; - tmp.operands().resize(s-2); - - with_exprt new_with_expr; - assert(new_with_expr.operands().size()==3); - new_with_expr.type()=expr.type(); - new_with_expr.old()=tmp; - new_with_expr.where()=expr.operands()[s-2]; - new_with_expr.new_value()=expr.operands()[s-1]; - - // recursive call - return convert_with(new_with_expr); - } - - const typet &expr_type=ns.follow(expr.type()); - - if(expr_type.id()==ID_array) - { - const exprt &array=expr.op0(); - - if(array.id()==ID_member) - { - // arrays in structs and unions are flattened! - - const typet &array_type=to_array_type(expr.type()); - const typet &elem_type=array_type.subtype(); - - const member_exprt &member_expr=to_member_expr(array); - const exprt &struct_op=member_expr.struct_op(); - const irep_idt &name=member_expr.get_component_name(); - - const typet &struct_op_type=ns.follow(struct_op.type()); - - std::size_t total_width=boolbv_width(struct_op_type); - - if(total_width==0) - throw "failed to get struct width"; - - std::size_t offset; - - if(struct_op_type.id()==ID_struct) - offset=boolbv_width.get_member( - to_struct_type(struct_op_type), name).offset; - else if(struct_op_type.id()==ID_union) - offset=0; - else - throw "failed to get offset"; - - std::size_t width=boolbv_width(expr.type()); - - if(width==0) - throw "failed to get struct member width"; - - std::size_t elem_width=boolbv_width(elem_type); - - if(elem_width==0) - throw "failed to get struct width"; - - std::size_t array_bits=(offset+width) - offset; - - assert(expr.operands().size()==3); - const exprt &index=expr.operands()[1]; - const exprt &value=expr.operands()[2]; - typecast_exprt index_tc(index, array_index_type()); - - out << "(bvor "; - out << "(bvand "; - - // this gets us the array - out << "(extract[" << offset+width-1 << ":" << offset << "] "; - convert_expr(struct_op, true); - out << ")"; - - // the mask - out << " (bvnot (bvshl"; - - out << " (concat"; - out << " (repeat[" << array_bits-elem_width << "] bv0[1])"; - out << " (repeat[" << elem_width << "] bv1[1])"; - out << ")"; // concat - - // shift it to the index - if(width>=array_index_bits) - out << " (zero_extend[" << width-array_index_bits << "]"; - else - out << " (extract[" << width-1 << ":0]"; - out << " (bvmul "; - convert_expr(index_tc, true); - out << " bv" << elem_width << "[" << array_index_bits << "]"; - out << "))))"; // bvmul, zero_extend, bvshl, bvneg - - out << ")"; // bvand - - // the new value - out << " (bvshl (zero_extend[" << array_bits-elem_width << "] "; - convert_expr(value, true); - - // shift it to the index - out << ")"; - if(width>=array_index_bits) - out << " (zero_extend[" << width-array_index_bits << "]"; - else - out << " (extract[" << width-1 << ":0]"; - out << " (bvmul "; - convert_expr(index_tc, true); - out << " bv" << elem_width << "[" << array_index_bits << "]"; - out << ")))"; // bvmul, bvshl, ze - - out << ")"; // bvor - } - else if(array.id()==ID_index) - { - // arrays in structs are flattened! - - const typet &array_type=to_array_type(expr.type()); - const typet &elem_type=array_type.subtype(); - - const index_exprt &index_expr=to_index_expr(array); - - std::size_t width=boolbv_width(expr.type()); - - if(width==0) - throw "failed to get width of 2nd dimension array"; - - std::size_t elem_width=boolbv_width(elem_type); - - if(elem_width==0) - throw "failed to get array element width"; - - assert(expr.operands().size()==3); - const exprt &index_2nd=expr.operands()[1]; - const exprt &value=expr.operands()[2]; - typecast_exprt index_tc(index_2nd, array_index_type()); - - out << "(bvor "; - out << "(bvand "; - - // this gets us the array - convert_expr(index_expr, true); - - // the mask - out << " (bvnot (bvshl"; - - out << " (concat"; - out << " (repeat[" << width-elem_width << "] bv0[1])"; - out << " (repeat[" << elem_width << "] bv1[1])"; - out << ")"; // concat - - // shift it to the index - if(width>=array_index_bits) - out << " (zero_extend[" << width-array_index_bits << "]"; - else - out << " (extract[" << width-1 << ":0]"; - out << " (bvmul "; - convert_expr(index_tc, true); - out << " bv" << elem_width << "[" << array_index_bits << "]"; - out << "))))"; // bvmul, zero_extend, bvshl, bvneg - - out << ")"; // bvand - - // the new value - out << " (bvshl (zero_extend[" << width-elem_width << "] "; - convert_expr(value, true); - // shift it to the index - out << ")"; - if(width>=array_index_bits) - out << " (zero_extend[" << width-array_index_bits << "]"; - else - out << " (extract[" << width-1 << ":0]"; - out << " (bvmul "; - convert_expr(index_tc, true); - out << " bv" << elem_width << "[" << array_index_bits << "]"; - out << ")))"; // bvmul, bvshl, ze - - out << ")"; // bvor - } - else - { - out << "(store "; - - convert_expr(expr.op0(), true); - - out << " "; - array_index(expr.op1()); - out << " "; - - // Booleans are put as bv[1] into an array - convert_expr(expr.op2(), true); - - out << ")"; - } - } - else if(expr_type.id()==ID_struct) - { - const struct_typet &struct_type=to_struct_type(expr_type); - - const exprt &index=expr.op1(); - const exprt &value=expr.op2(); - - std::size_t total_width=boolbv_width(expr.type()); - - if(total_width==0) - throw "failed to get struct width for with"; - - std::size_t width=boolbv_width(value.type()); - - if(width==0) - throw "failed to get member width for with"; - - std::size_t offset=boolbv_width.get_member( - struct_type, index.get(ID_component_name)).offset; - - if(total_width==width) - convert_expr(value, true); - else - { - if(offset+width!=total_width) - { - out << "(concat"; - out << " (extract[" << (total_width-1) << ":" << (offset+width) << "] "; - convert_expr(expr.op0(), true); - out << ")"; - } - - if(offset!=0) - out << " (concat"; - - out << " "; - convert_expr(value, true); - - if(offset!=0) - { - out << " (extract[" << (offset-1) << ":0] "; - convert_expr(expr.op0(), true); - out << ")"; - out << ")"; // concat - } - - if(offset+width!=total_width) - out << ")"; // concat - } - } - else if(expr_type.id()==ID_union) - { - const union_typet &union_type=to_union_type(expr_type); - - const exprt &value=expr.op2(); - - std::size_t total_width=boolbv_width(union_type); - - if(total_width==0) - throw "failed to get union width for with"; - - std::size_t member_width=boolbv_width(value.type()); - - if(member_width==0) - throw "failed to get union member width for with"; - - if(total_width==member_width) - convert_expr(value, true); - else - { - assert(total_width>member_width); - out << "(concat "; - out << "(extract[" - << (total_width-1) - << ":" << member_width << "] "; - convert_expr(expr.op0(), true); - out << ") "; // extract - convert_expr(value, true); - out << ")"; // concat - } - } - else if(expr_type.id()==ID_bv || - expr_type.id()==ID_unsignedbv || - expr_type.id()==ID_signedbv) - { - // Update bits in a bit-vector. We will use masking and shifts. - - std::size_t total_width=boolbv_width(expr_type); - - if(total_width==0) - throw "failed to get total width"; - - assert(expr.operands().size()==3); - const exprt &index=expr.operands()[1]; - const exprt &value=expr.operands()[2]; - - std::size_t value_width=boolbv_width(value.type()); - - if(value_width==0) - throw "failed to get value width"; - - typecast_exprt index_tc(index, expr_type); - - out << "(bvor "; - out << "(band "; - - // the mask to get rid of the old bits - out << " (bvnot (bvshl"; - - out << " (concat"; - out << " (repeat[" << total_width-value_width << "] bv0[1])"; - out << " (repeat[" << value_width << "] bv1[1])"; - out << ")"; // concat - - // shift it to the index - convert_expr(index_tc, true); - out << "))"; // bvshl, bvot - - out << ")"; // bvand - - // the new value - out << " (bvshl "; - convert_expr(value, true); - - // shift it to the index - convert_expr(index_tc, true); - out << ")"; // bvshl - - out << ")"; // bvor - } - else - { - throw "with expects struct, union, or array type, " - "but got "+expr.type().id_string(); - } -} - -void smt1_convt::convert_update(const exprt &expr) -{ - assert(expr.operands().size()==3); - - // todo - throw "smt1_convt::convert_update to be implemented"; -} - -void smt1_convt::convert_index(const index_exprt &expr, bool bool_as_bv) -{ - assert(expr.operands().size()==2); - - if(expr.array().id()==ID_member || - expr.array().id()==ID_index) - { - // arrays inside structs and 2-dimensional arrays - // these were flattened - - const typet &array_type=to_array_type(expr.array().type()); - const typet &elem_type=array_type.subtype(); - - std::size_t width=boolbv_width(expr.array().type()); - if(width==0) - throw "failed to get array width"; - - std::size_t elem_width=boolbv_width(elem_type); - - if(elem_width==0) - throw "failed to get struct width"; - - out << "(extract[" << elem_width-1 << ":0] "; - out << "(bvlshr "; - convert_expr(expr.array(), true); - if(width>=array_index_bits) - out << " (zero_extend[" << width-array_index_bits << "]"; - else - out << " (extract[" << width-1 << ":0]"; - out << " (bvmul "; - typecast_exprt index_tc(expr.index(), array_index_type()); - convert_expr(index_tc, true); - out << " bv" << elem_width << "[" << array_index_bits << "]"; - out << "))))"; - } - else - { - // Booleans out of arrays may have to be converted - from_bv_begin(expr.type(), bool_as_bv); - - out << "(select "; - convert_expr(expr.array(), true); - out << " "; - array_index(expr.index()); - out << ")"; - - // Booleans out of arrays may have to be converted - from_bv_end(expr.type(), bool_as_bv); - } -} - -void smt1_convt::convert_member(const member_exprt &expr, bool bool_as_bv) -{ - assert(expr.operands().size()==1); - - const member_exprt &member_expr=to_member_expr(expr); - const exprt &struct_op=member_expr.struct_op(); - const typet &struct_op_type=ns.follow(struct_op.type()); - const irep_idt &name=member_expr.get_component_name(); - - // Booleans pulled out of structs may have to be converted - from_bv_begin(expr.type(), bool_as_bv); - - if(struct_op_type.id()==ID_struct) - { - std::size_t offset=boolbv_width.get_member( - to_struct_type(struct_op_type), name).offset; - - std::size_t width=boolbv_width(expr.type()); - - if(width==0) - throw "failed to get struct member width"; - - out << "(extract[" - << (offset+width-1) - << ":" - << offset - << "] "; - convert_expr(struct_op, true); - out << ")"; - } - else if(struct_op_type.id()==ID_union) - { - std::size_t width=boolbv_width(expr.type()); - - if(width==0) - throw "failed to get union member width"; - - out << "(extract[" - << (width-1) - << ":0] "; - convert_expr(struct_op, true); - out << ")"; - } - else - assert(false); - - // Booleans pulled out of structs may have to be converted - from_bv_end(expr.type(), bool_as_bv); -} - -void smt1_convt::convert_overflow(const exprt &expr) -{ -} - -void smt1_convt::set_to(const exprt &expr, bool value) -{ - if(expr.id()==ID_and && value) - { - forall_operands(it, expr) - set_to(*it, true); - return; - } - - if(expr.id()==ID_not) - { - assert(expr.operands().size()==1); - return set_to(expr.op0(), !value); - } - - out << "\n"; - - find_symbols(expr); - - #if 0 - out << "; CONV: " - << format(expr) << '\n'; - #endif - - out << ":assumption ; set_to " << (value ? "true" : "false") << '\n' << " "; - - assert(expr.type().id()==ID_bool); - - if(!value) - { - out << "(not "; - convert_expr(expr, false); - out << ")"; - } - else - convert_expr(expr, false); - - out << "\n"; -} - -void smt1_convt::find_symbols(const exprt &expr) -{ - const typet &type=expr.type(); - find_symbols(type); - - if(expr.id()==ID_forall || expr.id()==ID_exists) - { - assert(expr.operands().size()==2); - assert(expr.op0().id()==ID_symbol); - - const irep_idt &ident=expr.op0().get(ID_identifier); - quantified_symbols.insert(ident); - find_symbols(expr.op1()); - quantified_symbols.erase(ident); - } - else - forall_operands(it, expr) - find_symbols(*it); - - if(expr.id()==ID_symbol || - expr.id()==ID_nondet_symbol) - { - // we don't track function-typed symbols - if(type.id()==ID_code) - return; - - irep_idt identifier; - - if(expr.id()==ID_symbol) - identifier=to_symbol_expr(expr).get_identifier(); - else - identifier="nondet_"+ - id2string(to_nondet_symbol_expr(expr).get_identifier()); - - if(quantified_symbols.find(identifier)!=quantified_symbols.end()) - return; // Symbol is quantified, i.e., it doesn't require declaration. - - identifiert &id=identifier_map[identifier]; - - if(id.type.is_nil()) - { - id.type=type; - - if(id.type.id()==ID_bool) - { - out << ":extrapreds((" - << convert_identifier(identifier) - << "))" << "\n"; - } - else - { - out << ":extrafuns((" - << convert_identifier(identifier) - << " "; - convert_type(type); - out << "))" << "\n"; - } - } - } - else if(expr.id()==ID_array_of) - { - if(array_of_map.find(expr)==array_of_map.end()) - { - irep_idt id="array_of'"+std::to_string(array_of_map.size()); - out << "; the following is a poor substitute for lambda i. x" << "\n"; - out << ":extrafuns((" - << id - << " "; - convert_type(type); - out << "))" << "\n"; - - // we can initialize array_ofs if they have - // a constant size and a constant element - if(type.find(ID_size)!=get_nil_irep() && - expr.op0().id()==ID_constant) - { - const array_typet &array_type=to_array_type(type); - mp_integer size; - - if(!to_integer(array_type.size(), size)) - { - // since we can't use quantifiers, let's enumerate... - for(mp_integer i=0; i rec_stack; - find_symbols_rec(type, rec_stack); -} - -void smt1_convt::find_symbols_rec( - const typet &type, - std::set &recstack) -{ - if(type.id()==ID_array) - { - const array_typet &array_type=to_array_type(type); - find_symbols(array_type.size()); - find_symbols_rec(array_type.subtype(), recstack); - } - else if(type.id()==ID_struct || - type.id()==ID_union) - { - const struct_union_typet::componentst &components= - to_struct_union_type(type).components(); - - for(const auto &comp : components) - find_symbols_rec(comp.type(), recstack); - } - else if(type.id()==ID_code) - { - const code_typet::parameterst ¶meters= - to_code_type(type).parameters(); - - for(const auto ¶m : parameters) - find_symbols_rec(param.type(), recstack); - - find_symbols_rec(to_code_type(type).return_type(), recstack); - } - else if(type.id()==ID_pointer) - { - find_symbols_rec(type.subtype(), recstack); - } - else if(type.id()==ID_incomplete_array) - { - find_symbols_rec(type.subtype(), recstack); - } - else if(type.id()==ID_symbol) - { - const symbol_typet &st=to_symbol_type(type); - const irep_idt &id=st.get_identifier(); - - if(recstack.find(id)==recstack.end()) - { - recstack.insert(id); - find_symbols_rec(ns.follow(type), recstack); - } - } -} - -exprt smt1_convt::binary2struct( - const struct_typet &type, - const std::string &binary) const -{ - const struct_typet::componentst &components=type.components(); - - std::size_t total_width=boolbv_width(type); - - if(total_width==0) - throw "failed to get struct width"; - - struct_exprt e(type); - e.reserve_operands(components.size()); - - std::size_t index=binary.size(); - for(const auto &comp : components) - { - const typet &sub_type=ns.follow(comp.type()); - - std::size_t sub_size=boolbv_width(sub_type); - - if(sub_size==0) - throw "failed to get component width"; - - index-=sub_size; - std::string cval=binary.substr(index, sub_size); - - e.copy_to_operands(ce_value(sub_type, "", cval, true)); - } - - return e; -} - -exprt smt1_convt::binary2union( - const union_typet &type, - const std::string &binary) const -{ - std::size_t total_width=boolbv_width(type); - - if(total_width==0) - throw "failed to get union width"; - - const union_typet::componentst &components=type.components(); - - // Taking the first component should work. - // Maybe a better idea is to take a largest component - std::size_t component_nr=0; - - // construct a union expr - union_exprt e(type); - e.set_component_number(component_nr); - e.set_component_name(components[component_nr].get_name()); - - const typet &sub_type=ns.follow(components[component_nr].type()); - std::size_t comp_width=boolbv_width(sub_type); - assert(comp_width<=total_width); - - std::string cval=binary.substr(total_width-comp_width, comp_width); - e.op()=ce_value(sub_type, "", cval, true); - - return e; -} - -void smt1_convt::flatten_array(const exprt &op) -{ - const array_typet array_type=to_array_type(op.type()); - const typet &elem_type=array_type.subtype(); - const exprt &size=array_type.size(); - - if(size.id()!=ID_constant) - throw "non-constant size array cannot be flattened"; - - mp_integer sizei; - if(to_integer(size, sizei)) - throw "array with non-constant size"; - - std::size_t elem_width=boolbv_width(elem_type); - - if(elem_width==0) - throw "failed to get width of array subtype"; - - #if 0 - out << " (let (?fbv "; - convert_expr(op, true); - out << ")"; - #endif - - for(mp_integer i=1; i0); - - if(num_ops==1) - convert_expr(expr.op0(), bool_as_bv); - else - { - exprt::operandst::const_iterator it= - expr.operands().begin(); - - for(std::size_t i=0; i -#include - -#include - -#include -#include -#include - -class byte_extract_exprt; -class typecast_exprt; -class constant_exprt; -class index_exprt; -class member_exprt; - -class smt1_convt:public prop_convt -{ -public: - enum class solvert - { - GENERIC, - BOOLECTOR, - CVC3, - CVC4, - MATHSAT, - OPENSMT, - YICES, - Z3 - }; - - smt1_convt( - const namespacet &_ns, - const std::string &_benchmark, - const std::string &_source, - const std::string &_logic, - solvert _solver, - std::ostream &_out): - prop_convt(_ns), - benchmark(_benchmark), - source(_source), - logic(_logic), - solver(_solver), - out(_out), - boolbv_width(_ns), - pointer_logic(_ns), - array_index_bits(32), - no_boolean_variables(0) - { - write_header(); - } - - virtual ~smt1_convt() { } - virtual resultt dec_solve(); - - // overloading interfaces - virtual literalt convert(const exprt &expr); - virtual void set_to(const exprt &expr, bool value); - virtual exprt get(const exprt &expr) const; - virtual tvt l_get(literalt) const; - virtual std::string decision_procedure_text() const { return "SMT1"; } - virtual void print_assignment(std::ostream &out) const; - -protected: - std::string benchmark, source, logic; - solvert solver; - std::ostream &out; - boolbv_widtht boolbv_width; - - void write_header(); - void write_footer(); - - // new stuff - void convert_expr(const exprt &expr, bool bool_as_bv); - void convert_type(const typet &type); - - // specific expressions go here - void convert_byte_update(const exprt &expr, bool bool_as_bv); - void convert_byte_extract( - const byte_extract_exprt &expr, - bool bool_as_bv); - void convert_typecast(const typecast_exprt &expr, bool bool_as_bv); - void convert_struct(const exprt &expr); - void convert_union(const exprt &expr); - void convert_constant(const constant_exprt &expr, bool bool_as_bv); - void convert_relation(const exprt &expr, bool bool_as_bv); - void convert_is_dynamic_object(const exprt &expr, bool bool_as_bv); - void convert_plus(const plus_exprt &expr); - void convert_minus(const minus_exprt &expr); - void convert_div(const div_exprt &expr); - void convert_mult(const mult_exprt &expr); - void convert_floatbv_plus(const exprt &expr); - void convert_floatbv_minus(const exprt &expr); - void convert_floatbv_div(const exprt &expr); - void convert_floatbv_mult(const exprt &expr); - void convert_mod(const mod_exprt &expr); - void convert_index(const index_exprt &expr, bool bool_as_bv); - void convert_member(const member_exprt &expr, bool bool_as_bv); - void convert_overflow(const exprt &expr); - void convert_with(const exprt &expr); - void convert_update(const exprt &expr); - - std::string convert_identifier(const irep_idt &identifier); - void convert_literal(const literalt l); - - // auxiliary methods - std::set quantified_symbols; - void find_symbols(const exprt &expr); - void find_symbols(const typet &type); - void find_symbols_rec(const typet &type, std::set &recstack); - void flatten_array(const exprt &op); - - // booleans vs. bit-vector[1] - void from_bv_begin(const typet &type, bool bool_as_bv); - void from_bv_end(const typet &type, bool bool_as_bv); - void from_bool_begin(const typet &type, bool bool_as_bv); - void from_bool_end(const typet &type, bool bool_as_bv); - - // arrays - typet array_index_type() const; - void array_index(const exprt &expr); - - // pointers - pointer_logict pointer_logic; - void convert_address_of_rec( - const exprt &expr, const pointer_typet &result_type); - - // keeps track of all symbols - struct identifiert - { - typet type; - exprt value; - - identifiert() - { - type.make_nil(); - value.make_nil(); - } - }; - - void set_value( - identifiert &identifier, - const std::string &index, - const std::string &value) - { - exprt tmp=ce_value(identifier.type, index, value, false); - if(tmp.id() == ID_array_list && identifier.value.id() == ID_array_list) - { - forall_operands(it, tmp) - identifier.value.copy_to_operands(*it); - } - else - identifier.value=tmp; - } - - typedef std::unordered_map identifier_mapt; - - identifier_mapt identifier_map; - - unsigned array_index_bits; - - // for replacing 'array_of' expressions - typedef std::map array_of_mapt; - array_of_mapt array_of_map; - - // for replacing 'array' expressions - typedef std::map array_expr_mapt; - array_expr_mapt array_expr_map; - - // for replacing string constants - typedef std::map string2array_mapt; - string2array_mapt string2array_map; - - exprt ce_value( - const typet &type, - const std::string &index, - const std::string &v, - bool in_struct) const; - - exprt binary2struct( - const struct_typet &type, - const std::string &binary) const; - - exprt binary2union( - const union_typet &type, - const std::string &binary) const; - - // flattens multi-operand expressions into binary - // expressions - void convert_nary(const exprt &expr, - const irep_idt op_string, - bool bool_as_bv); - - // Boolean part - unsigned no_boolean_variables; - std::vector boolean_assignment; -}; - -#endif // CPROVER_SOLVERS_SMT1_SMT1_CONV_H diff --git a/src/solvers/smt1/smt1_dec.cpp b/src/solvers/smt1/smt1_dec.cpp deleted file mode 100644 index 807fa527339..00000000000 --- a/src/solvers/smt1/smt1_dec.cpp +++ /dev/null @@ -1,667 +0,0 @@ -/*******************************************************************\ - -Module: - -Author: Daniel Kroening, kroening@kroening.com - -\*******************************************************************/ - -#include "smt1_dec.h" - -#include - -#if defined(__linux__) || \ - defined(__FreeBSD_kernel__) || \ - defined(__GNU__) || \ - defined(__unix__) || \ - defined(__CYGWIN__) || \ - defined(__MACH__) -#include -#endif - -#include -#include -#include -#include -#include -#include - -std::string smt1_dect::decision_procedure_text() const -{ - return "SMT1 "+logic+" using "+ - (solver==solvert::GENERIC?"Generic": - solver==solvert::BOOLECTOR?"Boolector": - solver==solvert::CVC3?"CVC3": - solver==solvert::CVC4?"CVC3": - solver==solvert::MATHSAT?"MathSAT": - solver==solvert::OPENSMT?"OpenSMT": - solver==solvert::YICES?"Yices": - solver==solvert::Z3?"Z3": - "(unknown)"); -} - -smt1_temp_filet::smt1_temp_filet() -{ - temp_out_filename=get_temporary_file("smt1_dec_out_", ""); - - temp_out.open( - temp_out_filename.c_str(), - std::ios_base::out | std::ios_base::trunc); -} - -smt1_temp_filet::~smt1_temp_filet() -{ - temp_out.close(); - - if(temp_out_filename!="") - unlink(temp_out_filename.c_str()); - - if(temp_result_filename!="") - unlink(temp_result_filename.c_str()); -} - -decision_proceduret::resultt smt1_dect::dec_solve() -{ - // SMT1 is really not incremental - assert(!dec_solve_was_called); - dec_solve_was_called=true; - - // this closes the SMT benchmark - write_footer(); - temp_out.close(); - - temp_result_filename= - get_temporary_file("smt1_dec_result_", ""); - - std::string command; - - switch(solver) - { - case solvert::BOOLECTOR: - // -rwl0 disables rewriting, which makes things slower, - // but in return values for arrays appear - // command = "boolector -rwl0 --smt " - // Removed as not necessarily needed on newer versions - command = "boolector --smt " - + temp_out_filename - + " --model --output " - + temp_result_filename; - break; - - case solvert::CVC3: - command = "cvc3 +model -lang smtlib -output-lang smtlib " - + temp_out_filename - + " > " - + temp_result_filename; - break; - - case solvert::CVC4: - command = "cvc4 -L smt1 " - + temp_out_filename - + " > " - + temp_result_filename; - break; - - case solvert::MATHSAT: - command = "mathsat -model -input=smt" - " < "+temp_out_filename - + " > "+temp_result_filename; - break; - - case solvert::OPENSMT: - command = "opensmt " - + temp_out_filename - + " > " - + temp_result_filename; - break; - - case solvert::YICES: - // command = "yices -smt -e " // Calling convention for older versions - command = "yices-smt --full-model " // Calling for 2.2.1 - + temp_out_filename - + " > " - + temp_result_filename; - break; - - case solvert::Z3: - command = "z3 -smt " - + temp_out_filename - + " > " - + temp_result_filename; - break; - - default: - assert(false); - } - - #if defined(__linux__) || defined(__APPLE__) - command+=" 2>&1"; - #endif - - int res=system(command.c_str()); - if(res<0) - { - error() << "error running SMT1 solver" << eom; - return decision_proceduret::resultt::D_ERROR; - } - - std::ifstream in(temp_result_filename.c_str()); - - switch(solver) - { - case solvert::BOOLECTOR: - return read_result_boolector(in); - - case solvert::CVC3: - return read_result_cvc3(in); - - case solvert::CVC4: - error() << "no support for CVC4 with SMT1, use SMT2 instead" << eom; - return decision_proceduret::resultt::D_ERROR; - - case solvert::MATHSAT: - return read_result_mathsat(in); - - case solvert::OPENSMT: - return read_result_opensmt(in); - - case solvert::YICES: - return read_result_yices(in); - - case solvert::Z3: - return read_result_z3(in); - - case solvert::GENERIC: - default: - error() << "Generic solver can't solve" << eom; - return decision_proceduret::resultt::D_ERROR; - } -} - -/// read model produced by Boolector -decision_proceduret::resultt smt1_dect::read_result_boolector(std::istream &in) -{ - std::string line; - - std::getline(in, line); - - if(line=="sat") - { - boolean_assignment.clear(); - boolean_assignment.resize(no_boolean_variables, false); - - typedef std::unordered_map valuest; - valuest values; - - while(std::getline(in, line)) - { - std::size_t pos=line.find(' '); - if(pos!=std::string::npos && pos!=0) - { - std::string id=std::string(line, 0, pos); - std::string value=std::string(line, pos+1, std::string::npos); - - // Boolector offers array values as follows: - // - // ID[INDEX] VALUE - // - // There may be more than one line per ID - - if(id!="" && id[id.size()-1]==']') // array? - { - std::size_t pos2=id.find('['); - - if(pos2!=std::string::npos) - { - std::string new_id=std::string(id, 0, pos2); - std::string index=std::string(id, pos2+1, id.size()-pos2-2); - values[new_id].index_value_map[index]=value; - } - } - else - values[id].value=value; - } - } - - // Theory variables - - for(identifier_mapt::iterator - it=identifier_map.begin(); - it!=identifier_map.end(); - it++) - { - it->second.value.make_nil(); - std::string conv_id=convert_identifier(it->first); - const valuet &v=values[conv_id]; - - for(valuet::index_value_mapt::const_iterator - i_it=v.index_value_map.begin(); i_it!=v.index_value_map.end(); i_it++) - set_value(it->second, i_it->first, i_it->second); - - if(v.value!="") - set_value(it->second, "", v.value); - } - - // Booleans - - for(unsigned v=0; v valuest; - valuest values; - - while(std::getline(in, line)) - { - if(line=="sat") - res=resultt::D_SATISFIABLE; - else if(line=="unsat") - res=resultt::D_UNSATISFIABLE; - else if(line.size()>=1 && line[0]=='(') - { - // (iff B0 true) - // (= c_h39__h39___CPROVER_malloc_size_h39_35_h39_1 bv0[64]) - // (= (select __h64_0 bv0[32]) bv5[8]) - std::size_t pos1=line.find(' '); - std::size_t pos2=line.rfind(' '); - if(pos1!=std::string::npos && - pos2!=std::string::npos && - pos1!=pos2) - { - std::string id=std::string(line, pos1+1, pos2-pos1-1); - std::string value=std::string(line, pos2+1, line.size()-pos2-2); - - if(has_prefix(id, "(select ")) - { - #if 0 - std::size_t pos3=id.rfind(' '); - std::string index=std::string(pos3+1, id.size()-pos3-1); - id=std::string(id, 8, pos3-8); - #endif - } - else - values[id].value=value; - } - } - } - - for(identifier_mapt::iterator - it=identifier_map.begin(); - it!=identifier_map.end(); - it++) - { - it->second.value.make_nil(); - std::string conv_id=convert_identifier(it->first); - std::string value=mathsat_value(values[conv_id].value); - - if(value!="") - set_value(it->second, "", value); - } - - // Booleans - for(unsigned v=0; v valuest; - valuest values; - - while(std::getline(in, line)) - { - if(line=="sat") - res = resultt::D_SATISFIABLE; - else if(line=="unsat") - res = resultt::D_UNSATISFIABLE; - else - { - std::size_t pos=line.find(" -> "); - if(pos!=std::string::npos) - values[std::string(line, 0, pos)]= - std::string(line, pos+4, std::string::npos); - } - } - - for(identifier_mapt::iterator - it=identifier_map.begin(); - it!=identifier_map.end(); - it++) - { - it->second.value.make_nil(); - std::string conv_id=convert_identifier(it->first); - std::string value=values[conv_id]; - if(value=="") - continue; - - exprt e; - if(string_to_expr_z3(it->second.type, value, e)) - it->second.value=e; - else - set_value(it->second, "", value); - } - - // Booleans - for(unsigned v=0; vsecond!=id) fit++; - - if(fit==array_of_map.end()) - return false; - - e = fit->first; - - return true; - } - else if(type.id()==ID_rational) - { - constant_exprt result; - result.type()=rational_typet(); - - if(value.substr(0, 4)=="val!") - result.set_value(value.substr(4)); - else - result.set_value(value); - - e = result; - return true; - } - - return false; -} - -decision_proceduret::resultt smt1_dect::read_result_cvc3(std::istream &in) -{ - std::string line; - decision_proceduret::resultt res = resultt::D_ERROR; - - boolean_assignment.clear(); - boolean_assignment.resize(no_boolean_variables, false); - - typedef std::unordered_map valuest; - valuest values; - - while(std::getline(in, line)) - { - if(line=="sat") - res = resultt::D_SATISFIABLE; - else if(line=="unsat") - res = resultt::D_UNSATISFIABLE; - else if(line.find("Current scope level")!=std::string::npos || - line.find("Variable Assignment")!=std::string::npos) - { - // ignore - } - else - { - assert(line.substr(0, 13)==" :assumption"); - std::size_t pos=line.find('('); - - if(pos!=std::string::npos) - { - std::string var; - std::string val; - - if(line[pos+1]=='=') - { - std::string ops = line.substr(pos+3, line.length()-pos-4); - std::size_t blank=ops.find(' '); - var = ops.substr(0, blank); - val = ops.substr(blank+1, ops.length()-blank); - - if((var.length()>=4 && var.substr(0, 4)=="cvc3") || - (val.length()>=4 && val.substr(0, 4)=="cvc3") || - var==val) - continue; - else if((var.substr(0, 9)=="array_of'") || - (var.substr(0, 2)=="bv" && val.substr(0, 2)!="bv")) - { - std::string t=var; var=val; val=t; - } - } - else if(line.substr(pos+1, 3)=="not") - { - var = line.substr(pos+5, line.length()-pos-6); - val = "false"; - } - else - { - var = line.substr(pos+1, line.length()-pos-2); - assert(var.find(' ')==std::string::npos); - val = "true"; - } - - values[var]=val; - } - } - } - - for(identifier_mapt::iterator - it=identifier_map.begin(); - it!=identifier_map.end(); - it++) - { - it->second.value.make_nil(); - std::string conv_id=convert_identifier(it->first); - std::string value=values[conv_id]; - if(value=="") - continue; - - if(value.substr(0, 2)=="bv") - { - std::string v=value.substr(2, value.find('[')-2); - size_t p = value.find('[')+1; - std::string w=value.substr(p, value.find(']')-p); - - std::string binary= - integer2binary( - string2integer(v, 10), - integer2unsigned(string2integer(w, 10))); - - set_value(it->second, "", binary); - } - else if(value=="false") - it->second.value=false_exprt(); - else if(value=="true") - it->second.value=true_exprt(); - else if(value.substr(0, 8)=="array_of") - { - // We assume that array_of has only concrete arguments... - irep_idt id(value); - array_of_mapt::const_iterator fit=array_of_map.begin(); - while(fit!=array_of_map.end() && fit->second!=id) fit++; - - if(fit!=array_of_map.end()) - it->second.value = fit->first; - } - else - set_value(it->second, "", value); - } - - // Booleans - for(unsigned v=0; v - -#include "smt1_conv.h" - -class smt1_temp_filet -{ -public: - smt1_temp_filet(); - ~smt1_temp_filet(); - -protected: - std::ofstream temp_out; - std::string temp_out_filename, temp_result_filename; -}; - -/*! \brief Decision procedure interface for various SMT 1.x solvers -*/ -class smt1_dect:protected smt1_temp_filet, public smt1_convt -{ -public: - smt1_dect( - const namespacet &_ns, - const std::string &_benchmark, - const std::string &_source, - const std::string &_logic, - solvert _solver): - smt1_temp_filet(), - smt1_convt(_ns, _benchmark, _source, _logic, _solver, temp_out), - logic(_logic), - dec_solve_was_called(false) - { - } - - virtual resultt dec_solve(); - virtual std::string decision_procedure_text() const; - -protected: - std::string logic; - bool dec_solve_was_called; - - resultt read_result_boolector(std::istream &in); - resultt read_result_cvc3(std::istream &in); - resultt read_result_opensmt(std::istream &in); - resultt read_result_mathsat(std::istream &in); - resultt read_result_yices(std::istream &in); - resultt read_result_z3(std::istream &in); - - bool string_to_expr_z3( - const typet &type, - const std::string &value, exprt &e) const; - - std::string mathsat_value(const std::string &src); - - struct valuet - { - // map from array index to value - typedef std::map index_value_mapt; - index_value_mapt index_value_map; - std::string value; - }; -}; - -#endif // CPROVER_SOLVERS_SMT1_SMT1_DEC_H From 738cf75ffb2e71d1f10478103ea2e64110ca14a5 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Sat, 28 Apr 2018 14:45:44 +0100 Subject: [PATCH 87/93] remove OpenSMT --- src/cbmc/cbmc_solvers.cpp | 2 -- src/solvers/smt2/smt2_conv.cpp | 1 - src/solvers/smt2/smt2_conv.h | 4 ---- src/solvers/smt2/smt2_dec.cpp | 9 --------- 4 files changed, 16 deletions(-) diff --git a/src/cbmc/cbmc_solvers.cpp b/src/cbmc/cbmc_solvers.cpp index 4195ad5fca8..e5a29ba7fe6 100644 --- a/src/cbmc/cbmc_solvers.cpp +++ b/src/cbmc/cbmc_solvers.cpp @@ -47,8 +47,6 @@ smt2_dect::solvert cbmc_solverst::get_smt2_solver_type() const s=smt2_dect::solvert::CVC3; else if(options.get_bool_option("cvc4")) s=smt2_dect::solvert::CVC4; - else if(options.get_bool_option("opensmt")) - s=smt2_dect::solvert::OPENSMT; else if(options.get_bool_option("yices")) s=smt2_dect::solvert::YICES; else if(options.get_bool_option("z3")) diff --git a/src/solvers/smt2/smt2_conv.cpp b/src/solvers/smt2/smt2_conv.cpp index 03bd1dc736f..9e46d45c67a 100644 --- a/src/solvers/smt2/smt2_conv.cpp +++ b/src/solvers/smt2/smt2_conv.cpp @@ -78,7 +78,6 @@ void smt2_convt::write_header() case solvert::CVC3: out << "; Generated for CVC 3\n"; break; case solvert::CVC4: out << "; Generated for CVC 4\n"; break; case solvert::MATHSAT: out << "; Generated for MathSAT\n"; break; - case solvert::OPENSMT: out << "; Generated for OPENSMT\n"; break; case solvert::YICES: out << "; Generated for Yices\n"; break; case solvert::Z3: out << "; Generated for Z3\n"; break; } diff --git a/src/solvers/smt2/smt2_conv.h b/src/solvers/smt2/smt2_conv.h index 665b747b58c..41d8564050b 100644 --- a/src/solvers/smt2/smt2_conv.h +++ b/src/solvers/smt2/smt2_conv.h @@ -35,7 +35,6 @@ class smt2_convt:public prop_convt CVC3, CVC4, MATHSAT, - OPENSMT, YICES, Z3 }; @@ -82,9 +81,6 @@ class smt2_convt:public prop_convt case solvert::MATHSAT: break; - case solvert::OPENSMT: - break; - case solvert::YICES: break; diff --git a/src/solvers/smt2/smt2_dec.cpp b/src/solvers/smt2/smt2_dec.cpp index 63bd0afaeca..e303701d26c 100644 --- a/src/solvers/smt2/smt2_dec.cpp +++ b/src/solvers/smt2/smt2_dec.cpp @@ -37,7 +37,6 @@ std::string smt2_dect::decision_procedure_text() const solver==solvert::CVC3?"CVC3": solver==solvert::CVC4?"CVC4": solver==solvert::MATHSAT?"MathSAT": - solver==solvert::OPENSMT?"OpenSMT": solver==solvert::YICES?"Yices": solver==solvert::Z3?"Z3": "(unknown)"); @@ -126,14 +125,6 @@ decision_proceduret::resultt smt2_dect::dec_solve() + " > "+smt2_temp_file.temp_result_filename; break; - case solvert::OPENSMT: - command = "opensmt " - + smt2_temp_file.temp_out_filename - + " > " - + smt2_temp_file.temp_result_filename; - break; - - case solvert::YICES: // command = "yices -smt -e " // Calling convention for older versions command = "yices-smt2 " // Calling for 2.2.1 From 5c9419a57f8af3640129cf91803749b2a069598c Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Sat, 28 Apr 2018 17:01:38 +0100 Subject: [PATCH 88/93] remove bmc_constraints --- src/cbmc/bmc.cpp | 8 -------- src/cbmc/bmc.h | 3 --- 2 files changed, 11 deletions(-) diff --git a/src/cbmc/bmc.cpp b/src/cbmc/bmc.cpp index e236091631a..34edbb516a6 100644 --- a/src/cbmc/bmc.cpp +++ b/src/cbmc/bmc.cpp @@ -118,14 +118,6 @@ void bmct::do_conversion() // convert SSA equation.convert(prop_conv); - // the 'extra constraints' - if(!bmc_constraints.empty()) - { - status() << "converting constraints" << eom; - - for(const auto &constraint : bmc_constraints) - prop_conv.set_to_true(constraint); - } // hook for cegis to freeze synthesis program vars freeze_program_variables(); } diff --git a/src/cbmc/bmc.h b/src/cbmc/bmc.h index 907c9bdd4fd..551fa7c2b3d 100644 --- a/src/cbmc/bmc.h +++ b/src/cbmc/bmc.h @@ -94,9 +94,6 @@ class bmct:public safety_checkert safety_checkert::resultt execute(abstract_goto_modelt &); virtual ~bmct() { } - // additional stuff - std::list bmc_constraints; - void set_ui(ui_message_handlert::uit _ui) { ui=_ui; } // the safety_checkert interface From 4a8107f19eb2b9a46ef0ddf0bde5efe011f96736 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Mon, 30 Apr 2018 11:50:51 +0100 Subject: [PATCH 89/93] missing const for parameter --- src/java_bytecode/java_class_loader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java_bytecode/java_class_loader.h b/src/java_bytecode/java_class_loader.h index 6f46072aaa2..6634172da93 100644 --- a/src/java_bytecode/java_class_loader.h +++ b/src/java_bytecode/java_class_loader.h @@ -55,7 +55,7 @@ class java_class_loadert:public messaget java_class_loader_limitt &class_loader_limit, const irep_idt &class_name); - void set_java_cp_include_files(std::string &java_cp_include_files) + void set_java_cp_include_files(const std::string &java_cp_include_files) { this->java_cp_include_files = java_cp_include_files; } From d11590438a1ef2c2aa5a2d17f99510a88c21deb8 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Mon, 30 Apr 2018 20:33:03 +0100 Subject: [PATCH 90/93] fix a comment --- src/java_bytecode/jar_file.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/java_bytecode/jar_file.cpp b/src/java_bytecode/jar_file.cpp index b289f4e2d3a..ff0f068a748 100644 --- a/src/java_bytecode/jar_file.cpp +++ b/src/java_bytecode/jar_file.cpp @@ -24,8 +24,7 @@ void jar_filet::initialize_file_index(java_class_loader_limitt &limit) } /// This constructor creates a jar_file object whose contents -/// are extracted from a memory buffer (byte array) as opposed -/// to a jar file. +/// are extracted from a file with given name. jar_filet::jar_filet( java_class_loader_limitt &limit, const std::string &filename): From f3d52234cf832c6fca0b04afebaffc10e3798567 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Tue, 1 May 2018 12:38:02 +0100 Subject: [PATCH 91/93] cleanup the includes in src/java_bytecode --- src/java_bytecode/ci_lazy_methods.h | 12 +++++++----- src/java_bytecode/java_bytecode_convert_method.h | 8 ++++---- .../java_bytecode_convert_method_class.h | 8 +++++--- src/java_bytecode/java_bytecode_language.h | 15 +++++++-------- src/java_bytecode/java_entry_point.h | 5 +++-- src/java_bytecode/java_object_factory.h | 6 +++--- src/java_bytecode/java_static_initializers.h | 7 ++++--- src/java_bytecode/object_factory_parameters.h | 2 ++ 8 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/java_bytecode/ci_lazy_methods.h b/src/java_bytecode/ci_lazy_methods.h index 11095fa3d8a..71eb718fe42 100644 --- a/src/java_bytecode/ci_lazy_methods.h +++ b/src/java_bytecode/ci_lazy_methods.h @@ -12,18 +12,20 @@ #ifndef CPROVER_JAVA_BYTECODE_GATHER_METHODS_LAZILY_H #define CPROVER_JAVA_BYTECODE_GATHER_METHODS_LAZILY_H +#include "ci_lazy_methods_needed.h" +#include "java_bytecode_parse_tree.h" +#include "java_class_loader.h" +#include "select_pointer_type.h" +#include "synthetic_methods_map.h" + #include #include #include #include #include + #include -#include -#include -#include -#include -#include class java_string_library_preprocesst; diff --git a/src/java_bytecode/java_bytecode_convert_method.h b/src/java_bytecode/java_bytecode_convert_method.h index 90e76f501f9..2ef174dbda9 100644 --- a/src/java_bytecode/java_bytecode_convert_method.h +++ b/src/java_bytecode/java_bytecode_convert_method.h @@ -12,12 +12,12 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_METHOD_H #define CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_METHOD_H -#include -#include +#include "ci_lazy_methods_needed.h" +#include "java_bytecode_parse_tree.h" #include "java_string_library_preprocess.h" -#include "java_bytecode_parse_tree.h" -#include +#include +#include class class_hierarchyt; diff --git a/src/java_bytecode/java_bytecode_convert_method_class.h b/src/java_bytecode/java_bytecode_convert_method_class.h index 0df926b1005..5ec7b38fb22 100644 --- a/src/java_bytecode/java_bytecode_convert_method_class.h +++ b/src/java_bytecode/java_bytecode_convert_method_class.h @@ -12,14 +12,16 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_METHOD_CLASS_H #define CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_METHOD_CLASS_H +#include "ci_lazy_methods_needed.h" +#include "java_bytecode_parse_tree.h" +#include "java_bytecode_convert_class.h" + #include #include #include #include + #include -#include "java_bytecode_parse_tree.h" -#include "java_bytecode_convert_class.h" -#include #include #include diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h index 47d5fb69d82..bb3912fa150 100644 --- a/src/java_bytecode/java_bytecode_language.h +++ b/src/java_bytecode/java_bytecode_language.h @@ -10,22 +10,21 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_LANGUAGE_H #define CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_LANGUAGE_H -#include - -#include -#include - -#include - #include "ci_lazy_methods.h" #include "ci_lazy_methods_needed.h" #include "java_class_loader.h" #include "java_static_initializers.h" #include "java_string_library_preprocess.h" #include "object_factory_parameters.h" +#include "select_pointer_type.h" #include "synthetic_methods_map.h" -#include +#include + +#include +#include + +#include #define JAVA_BYTECODE_LANGUAGE_OPTIONS /*NOLINT*/ \ "(no-core-models)" \ diff --git a/src/java_bytecode/java_entry_point.h b/src/java_bytecode/java_entry_point.h index 399078ee2f8..006334ff99c 100644 --- a/src/java_bytecode/java_entry_point.h +++ b/src/java_bytecode/java_entry_point.h @@ -10,10 +10,11 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_JAVA_BYTECODE_JAVA_ENTRY_POINT_H #define CPROVER_JAVA_BYTECODE_JAVA_ENTRY_POINT_H +#include "java_bytecode_language.h" +#include "select_pointer_type.h" + #include #include -#include -#include #define JAVA_ENTRY_POINT_RETURN_SYMBOL "return'" #define JAVA_ENTRY_POINT_EXCEPTION_SYMBOL "uncaught_exception'" diff --git a/src/java_bytecode/java_object_factory.h b/src/java_bytecode/java_object_factory.h index a5ba9ea5500..0d8ec5f0995 100644 --- a/src/java_bytecode/java_object_factory.h +++ b/src/java_bytecode/java_object_factory.h @@ -68,13 +68,13 @@ Author: Daniel Kroening, kroening@kroening.com #ifndef CPROVER_JAVA_BYTECODE_JAVA_OBJECT_FACTORY_H #define CPROVER_JAVA_BYTECODE_JAVA_OBJECT_FACTORY_H +#include "java_bytecode_language.h" +#include "select_pointer_type.h" + #include #include #include -#include -#include - /// Selects the kind of allocation used by java_object_factory et al. enum class allocation_typet { diff --git a/src/java_bytecode/java_static_initializers.h b/src/java_bytecode/java_static_initializers.h index 6b65a29459d..992e9b6425b 100644 --- a/src/java_bytecode/java_static_initializers.h +++ b/src/java_bytecode/java_static_initializers.h @@ -9,13 +9,14 @@ Author: Chris Smowton, chris.smowton@diffblue.com #ifndef CPROVER_JAVA_BYTECODE_JAVA_STATIC_INITIALIZERS_H #define CPROVER_JAVA_BYTECODE_JAVA_STATIC_INITIALIZERS_H +#include "object_factory_parameters.h" +#include "select_pointer_type.h" +#include "synthetic_methods_map.h" + #include #include #include -#include -#include -#include irep_idt clinit_wrapper_name(const irep_idt &class_name); diff --git a/src/java_bytecode/object_factory_parameters.h b/src/java_bytecode/object_factory_parameters.h index 5e0785bf7a7..17b838242c2 100644 --- a/src/java_bytecode/object_factory_parameters.h +++ b/src/java_bytecode/object_factory_parameters.h @@ -12,6 +12,8 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include + #define MAX_NONDET_ARRAY_LENGTH_DEFAULT 5 #define MAX_NONDET_STRING_LENGTH std::numeric_limits::max() #define MAX_NONDET_TREE_DEPTH 5 From 2aaad80d6599b5bb68ab7782125c2d85ab8800cd Mon Sep 17 00:00:00 2001 From: Kurt Degiorgio Date: Mon, 12 Feb 2018 09:44:45 +0000 Subject: [PATCH 92/93] Modifies the instrumented clinit_wrapper function The previous version of clinit_wrapper did not conform to the JVM specification (section 5.5) as it did not support concurrency. More specifically, the clinit_wrapper has to be carefully synchronised as other threads may try to initialize a given class or interface at the same-time. This commit makes the clinit_wrapper thread-safe by introducing a critical section and two state variables. The commit implements a simplification of the algorithm defined in section 5.5 of the JVM specification. For instance, exceptions thrown during the execution of static initializers are not properly handled. --- .../java_static_initializers.cpp | 454 +++++++++++++++--- src/java_bytecode/java_static_initializers.h | 3 +- 2 files changed, 379 insertions(+), 78 deletions(-) diff --git a/src/java_bytecode/java_static_initializers.cpp b/src/java_bytecode/java_static_initializers.cpp index eefa2a42eb7..c3721978606 100644 --- a/src/java_bytecode/java_static_initializers.cpp +++ b/src/java_bytecode/java_static_initializers.cpp @@ -14,6 +14,34 @@ Author: Chris Smowton, chris.smowton@diffblue.com #include #include #include +#include + +/// The three states in which a `` method for a class can be before, +/// after, and during static class initialization. +/// +/// According to the JVM Spec document (section 5.5), the JVM needs to +/// maintain, for every class initializer, a state indicating whether the +/// initializer has been executed, is being executed, or has raised errors. +/// The spec mandates that the JVM consider 4 different states (not +/// initialized, being initialized, ready for use, and initialization error). +/// The `clinit_statet` is a simplification of those 4 states where: +/// +/// `NOT_INIT` corresponds to "not initialized" +/// `IN_PROGRESS` corresponds to "some thread is currently running the +/// `` and no other thread should run it" +/// `INIT_COMPLETE` corresponds to "the `` has been executed and the +/// class is ready to be used, or it has errored" +/// +/// The last state corresponds to a fusion of the two original states "ready +/// for use" and "initialization error". +enum class clinit_statest +{ + NOT_INIT, + IN_PROGRESS, + INIT_COMPLETE +}; + +const typet clinit_states_type = java_byte_type(); // Disable linter here to allow a std::string constant, since that holds // a length, whereas a cstr would require strlen every time. @@ -39,13 +67,35 @@ bool is_clinit_wrapper_function(const irep_idt &function_id) return has_suffix(id2string(function_id), clinit_wrapper_suffix); } -/// Get name of the static-initialization-already-done global variable for a -/// given class. -/// \param class_name: class symbol name -/// \return static initializer wrapper-already run global name -static irep_idt clinit_already_run_variable_name(const irep_idt &class_name) +/// Add a new symbol to the symbol table. +/// Note: assumes that a symbol with this name does not exist. +/// /param name: name of the symbol to be generated +/// /param type: type of the symbol to be generated +/// /param value: initial value of the symbol to be generated +/// /param is_thread_local: if true this symbol will be set as thread local +/// /param is_static_lifetime: if true this symbol will be set as static +/// /return returns new symbol. +static symbolt add_new_symbol( + symbol_table_baset &symbol_table, + const irep_idt &name, + const typet &type, + const exprt &value, + const bool is_thread_local, + const bool is_static_lifetime) { - return id2string(class_name) + "::clinit_already_run"; + symbolt new_symbol; + new_symbol.name = name; + new_symbol.pretty_name = name; + new_symbol.base_name = name; + new_symbol.type = type; + new_symbol.value = value; + new_symbol.is_lvalue = true; + new_symbol.is_state_var = true; + new_symbol.is_static_lifetime = is_static_lifetime; + new_symbol.is_thread_local = is_thread_local; + new_symbol.mode = ID_java; + symbol_table.add(new_symbol); + return new_symbol; } /// Get name of the real static initializer for a given class. Doesn't check @@ -57,6 +107,64 @@ static irep_idt clinit_function_name(const irep_idt &class_name) return id2string(class_name) + clinit_function_suffix; } +/// Get name of the static-initialization-state global variable for a +/// given class. +/// \param class_name: class symbol name +/// \return static initializer wrapper-state variable global name +static irep_idt clinit_state_var_name(const irep_idt &class_name) +{ + return id2string(class_name) + CPROVER_PREFIX "clinit_state"; +} + +/// Get name of the static-initialization-state local state variable for a +/// given class. +/// \param class_name: class symbol name +/// \return static initializer wrapper-state local state variable name +static irep_idt clinit_thread_local_state_var_name(const irep_idt &class_name) +{ + return id2string(class_name) + CPROVER_PREFIX "clinit_threadlocal_state"; +} + +/// Get name of the static-initialization local variable for a given class. +/// \param class_name: class symbol name +/// \return static initializer wrapper-state local variable +static irep_idt clinit_local_init_complete_var_name(const irep_idt &class_name) +{ + return id2string(class_name) + CPROVER_PREFIX "clinit_wrapper::init_complete"; +} + +/// Generates a code_assignt for clinit_statest +/// /param expr: +/// expression to be used as the LHS of generated assignment. +/// /param state: +/// execution state of the clint_wrapper, used as the RHS of the generated +/// assignment. +/// /return returns a code_assignt, assigning \p expr to the integer +/// representation of \p state +static code_assignt +gen_clinit_assignexpr(const exprt &expr, const clinit_statest state) +{ + mp_integer initv(static_cast(state)); + constant_exprt init_s = from_integer(initv, clinit_states_type); + return code_assignt(expr, init_s); +} + +/// Generates an equal_exprt for clinit_statest +/// /param expr: +/// expression to be used as the LHS of generated eqaul exprt. +/// /param state: +/// execution state of the clint_wrapper, used as the RHS of the generated +/// equal exprt. +/// /return returns a equal_exprt, equating \p expr to the integer +/// representation of \p state +static equal_exprt +gen_clinit_eqexpr(const exprt &expr, const clinit_statest state) +{ + mp_integer initv(static_cast(state)); + constant_exprt init_s = from_integer(initv, clinit_states_type); + return equal_exprt(expr, init_s); +} + /// Checks whether a static initializer wrapper is needed for a given class, /// i.e. if the given class or any superclass has a static initializer. /// \param class_name: class symbol name @@ -96,21 +204,29 @@ static void create_clinit_wrapper_symbols( symbol_tablet &symbol_table, synthetic_methods_mapt &synthetic_methods) { - const irep_idt &already_run_name = - clinit_already_run_variable_name(class_name); - symbolt already_run_symbol; - already_run_symbol.name = already_run_name; - already_run_symbol.pretty_name = already_run_name; - already_run_symbol.base_name = "clinit_already_run"; - already_run_symbol.type = bool_typet(); - already_run_symbol.value = false_exprt(); - already_run_symbol.is_lvalue = true; - already_run_symbol.is_state_var = true; - already_run_symbol.is_static_lifetime = true; - already_run_symbol.mode = ID_java; - bool failed = symbol_table.add(already_run_symbol); - INVARIANT(!failed, "clinit-already-run symbol should be fresh"); - + exprt not_init_value = from_integer( + static_cast(clinit_statest::NOT_INIT), clinit_states_type); + + // Create two global static synthetic "fields" for the class "id" + // these two variables hold the state of the class initialization algorithm + // across calls to the clinit_wrapper + add_new_symbol( + symbol_table, + clinit_state_var_name(class_name), + clinit_states_type, + not_init_value, + false, + true); + + add_new_symbol( + symbol_table, + clinit_thread_local_state_var_name(class_name), + clinit_states_type, + not_init_value, + true, + true); + + // Create symbol for the "clinit_wrapper" symbolt wrapper_method_symbol; code_typet wrapper_method_type; wrapper_method_type.return_type() = void_typet(); @@ -126,7 +242,7 @@ static void create_clinit_wrapper_symbols( // java_bytecode_convert_methodt::convert wrapper_method_symbol.type.set(ID_C_class, class_name); wrapper_method_symbol.mode = ID_java; - failed = symbol_table.add(wrapper_method_symbol); + bool failed = symbol_table.add(wrapper_method_symbol); INVARIANT(!failed, "clinit-wrapper symbol should be fresh"); auto insert_result = synthetic_methods.emplace( @@ -138,82 +254,266 @@ static void create_clinit_wrapper_symbols( "clinit wrapper"); } -/// Produces the static initialiser wrapper body for the given function. +/// Produces the static initialiser wrapper body for the given function. This +/// static initializer implements (a simplification of) the algorithm defined +/// in Section 5.5 of the JVM Specs. This function, or wrapper, checks whether +/// static init has already taken place, calls the actual `` method if +/// not, and possibly recursively initializes super-classes and interfaces. +/// Assume that C is the class to be initialized and that C extends C' and +/// implements interfaces I1 ... In, then the algorithm is as follows: +/// +/// \code +/// +/// bool init_complete; +/// if(java::C::__CPROVER_PREFIX_clinit_thread_local_state == INIT_COMPLETE) +/// { +/// return; +/// } +/// java::C::__CPROVER_PREFIX_clinit_thread_local_state = INIT_COMPLETE; +/// +/// // This thread atomically checks and sets the global variable +/// // 'clinit_state' in order to ensure that only this thread runs the +/// // static initializer. The assume() statement below will prevent the SAT +/// // solver from producing a thread schedule where more than 1 thread is +/// // running the initializer. At the end of this function the only +/// // thread that runs the static initializer will update the variable. +/// // Alternatively we could have done a busy wait / spin-lock, but that +/// // would achieve the same effect and blow up the size of the SAT formula. +/// ATOMIC_BEGIN +/// assume(java::C::__CPROVER_PREFIX_clinit_state != IN_PROGRESS) +/// if(java::C::__CPROVER_PREFIX_clinit_state == NOT_INIT) +/// { +/// java::C::__CPROVER_PREFIX_clinit_state = IN_PROGRESS +/// init_complete = false; +/// } +/// else if(java::C::__CPROVER_PREFIX_clinit_state == INIT_COMPLETE) +/// { +/// init_complete = true; +/// } +/// ATOMIC_END +/// +/// if(init_complete) +/// return; +/// +/// java::C'::clinit_wrapper(); +/// java::I1::clinit_wrapper(); +/// java::I2::clinit_wrapper(); +/// // ... +/// java::In::clinit_wrapper(); +/// +/// java::C::(); +/// +/// // Setting this variable to INIT_COMPLETE will let other threads "cross" +/// // beyond the assume() statement above in this function. +/// ATOMIC_START +/// C::__CPROVER_PREFIX_clinit_state = INIT_COMPLETE; +/// ATOMIC_END +/// +/// return; +/// +/// \endcode +/// +/// Note: The current implementation does not deal with exceptions. +/// /// \param function_id: clinit wrapper function id (the wrapper_method_symbol /// name created by `create_clinit_wrapper_symbols`) /// \param symbol_table: global symbol table /// \return the body of the static initialiser wrapper codet get_clinit_wrapper_body( - const irep_idt &function_id, const symbol_table_baset &symbol_table) + const irep_idt &function_id, + symbol_table_baset &symbol_table) { - // Assume that class C extends class C' and implements interfaces - // I1, ..., In. We now create the following function (possibly recursively - // creating the clinit_wrapper functions for C' and I1, ..., In): - // - // java::C::clinit_wrapper() - // { - // if (java::C::clinit_already_run == false) - // { - // java::C::clinit_already_run = true; // before recursive calls! - // - // java::C'::clinit_wrapper(); - // java::I1::clinit_wrapper(); - // java::I2::clinit_wrapper(); - // // ... - // java::In::clinit_wrapper(); - // - // java::C::(); - // } - // } const symbolt &wrapper_method_symbol = symbol_table.lookup_ref(function_id); irep_idt class_name = wrapper_method_symbol.type.get(ID_C_class); INVARIANT( !class_name.empty(), "wrapper function should be annotated with its class"); - const symbolt &already_run_symbol = - symbol_table.lookup_ref(clinit_already_run_variable_name(class_name)); - equal_exprt check_already_run( - already_run_symbol.symbol_expr(), - false_exprt()); + const symbolt &clinit_state_sym = + symbol_table.lookup_ref(clinit_state_var_name(class_name)); + const symbolt &clinit_thread_local_state_sym = + symbol_table.lookup_ref(clinit_thread_local_state_var_name(class_name)); + + // Create a function-local variable "init_complete". This variable is used to + // avoid inspecting the global state (clinit_state_sym) outside of + // the critical-section. + const symbolt &init_complete = add_new_symbol( + symbol_table, + clinit_local_init_complete_var_name(class_name), + bool_typet(), + nil_exprt(), + true, + false); + + code_blockt function_body; + codet atomic_begin(ID_atomic_begin); + codet atomic_end(ID_atomic_end); + +#if 0 + // This code defines source locations for every codet generated below for + // the static initializer wrapper. Enable this for debugging the symex going + // through the clinit_wrapper. + // + // java::C::clinit_wrapper() + // You will additionally need to associate the `location` with the + // `function_body` and then manually set lines of code for each of the + // statements of the function, using something along the lines of: + // `mycodet.then_case().add_source_location().set_line(17);`/ + + source_locationt &location = function_body.add_source_location(); + location.set_file (""); + location.set_line (""); + location.set_function (clinit_wrapper_name); + std::string comment = + "Automatically generated function. States are:\n" + " 0 = class not initialized, init val of clinit_state/clinit_local_state\n" + " 1 = class initialization in progress, by this or another thread\n" + " 2 = initialization finished with success, by this or another thread\n"; + static_assert((int) clinit_statest::NOT_INIT==0, "Check commment above"); + static_assert((int) clinit_statest::IN_PROGRESS==1, "Check comment above"); + static_assert((int) clinit_statest::INIT_COMPLETE==2, "Check comment above"); +#endif + + // bool init_complete; + { + code_declt decl(init_complete.symbol_expr()); + function_body.add(decl); + } + + // if(C::__CPROVER_PREFIX_clinit_thread_local_state == INIT_COMPLETE) return; + { + code_ifthenelset conditional; + conditional.cond() = gen_clinit_eqexpr( + clinit_thread_local_state_sym.symbol_expr(), + clinit_statest::INIT_COMPLETE); + conditional.then_case() = code_returnt(); + function_body.add(conditional); + } - // the entire body of the function is an if-then-else - code_ifthenelset wrapper_body; + // C::__CPROVER_PREFIX_clinit_thread_local_state = INIT_COMPLETE; + { + code_assignt assign = gen_clinit_assignexpr( + clinit_thread_local_state_sym.symbol_expr(), + clinit_statest::INIT_COMPLETE); + function_body.add(assign); + } - // add the condition to the if - wrapper_body.cond()=check_already_run; + // ATOMIC_BEGIN + { + function_body.add(atomic_begin); + } - // add the "already-run = false" statement - code_blockt init_body; - code_assignt set_already_run(already_run_symbol.symbol_expr(), true_exprt()); - init_body.move_to_operands(set_already_run); + // Assume: clinit_state_sym != IN_PROGRESS + { + exprt assumption = gen_clinit_eqexpr( + clinit_state_sym.symbol_expr(), clinit_statest::IN_PROGRESS); + assumption = not_exprt(assumption); + code_assumet assume(assumption); + function_body.add(assume); + } - // iterate through the base types and add recursive calls to the - // clinit_wrapper() - const symbolt &class_symbol = symbol_table.lookup_ref(class_name); - for(const auto &base : to_class_type(class_symbol.type).bases()) + // If(C::__CPROVER_PREFIX_clinit_state == NOT_INIT) + // { + // C::__CPROVER_PREFIX_clinit_state = IN_PROGRESS; + // init_complete = false; + // } + // else If(C::__CPROVER_PREFIX_clinit_state == INIT_COMPLETE) + // { + // init_complete = true; + // } { - const auto base_name = to_symbol_type(base.type()).get_identifier(); - irep_idt base_init_routine = clinit_wrapper_name(base_name); - auto findit = symbol_table.symbols.find(base_init_routine); - if(findit == symbol_table.symbols.end()) - continue; - code_function_callt call_base; - call_base.function() = findit->second.symbol_expr(); - init_body.move_to_operands(call_base); + code_ifthenelset not_init_conditional; + code_blockt then_block; + not_init_conditional.cond() = gen_clinit_eqexpr( + clinit_state_sym.symbol_expr(), clinit_statest::NOT_INIT); + then_block.add( + gen_clinit_assignexpr( + clinit_state_sym.symbol_expr(), clinit_statest::IN_PROGRESS)); + then_block.add(code_assignt(init_complete.symbol_expr(), false_exprt())); + not_init_conditional.then_case() = then_block; + + code_ifthenelset init_conditional; + code_blockt init_conditional_body; + init_conditional.cond() = gen_clinit_eqexpr( + clinit_state_sym.symbol_expr(), clinit_statest::INIT_COMPLETE); + init_conditional_body.add( + code_assignt(init_complete.symbol_expr(), true_exprt())); + init_conditional.then_case() = init_conditional_body; + not_init_conditional.else_case() = init_conditional; + function_body.add(not_init_conditional); + } + + // ATOMIC_END + { + function_body.add(atomic_end); + } + + // if(init_complete) return; + { + code_ifthenelset conditional; + conditional.cond() = init_complete.symbol_expr(); + conditional.then_case() = code_returnt(); + function_body.add(conditional); + } + + // Initialize the super-class C' and + // the implemented interfaces l_1 ... l_n. + // see JVMS p.359 step 7, for the exact definition of + // the sequence l_1 to l_n. + // This is achieved by iterating through the base types and + // adding recursive calls to the clinit_wrapper() + // + // java::C'::clinit_wrapper(); + // java::I1::clinit_wrapper(); + // java::I2::clinit_wrapper(); + // // ... + // java::In::clinit_wrapper(); + // + // java::C::(); + // + code_blockt init_body; + { + // iterate through the base types and add recursive calls to the + // clinit_wrapper() + const symbolt &class_symbol = symbol_table.lookup_ref(class_name); + for(const auto &base : to_class_type(class_symbol.type).bases()) + { + const auto base_name = to_symbol_type(base.type()).get_identifier(); + irep_idt base_init_routine = clinit_wrapper_name(base_name); + auto findit = symbol_table.symbols.find(base_init_routine); + if(findit == symbol_table.symbols.end()) + continue; + code_function_callt call_base; + call_base.function() = findit->second.symbol_expr(); + init_body.move_to_operands(call_base); + } + + // call java::C::(), if the class has one static initializer + const irep_idt &real_clinit_name = clinit_function_name(class_name); + auto find_sym_it = symbol_table.symbols.find(real_clinit_name); + if(find_sym_it != symbol_table.symbols.end()) + { + code_function_callt call_real_init; + call_real_init.function() = find_sym_it->second.symbol_expr(); + init_body.move_to_operands(call_real_init); + } } + function_body.append(init_body); - // call java::C::(), if the class has one static initializer - const irep_idt &real_clinit_name = clinit_function_name(class_name); - auto find_sym_it = symbol_table.symbols.find(real_clinit_name); - if(find_sym_it!=symbol_table.symbols.end()) + // ATOMIC_START + // C::__CPROVER_PREFIX_clinit_state = INIT_COMPLETE; + // ATOMIC_END + // return; { - code_function_callt call_real_init; - call_real_init.function()=find_sym_it->second.symbol_expr(); - init_body.move_to_operands(call_real_init); + // synchronization prologue + function_body.add(atomic_begin); + function_body.add( + gen_clinit_assignexpr( + clinit_state_sym.symbol_expr(), clinit_statest::INIT_COMPLETE)); + function_body.add(atomic_end); + function_body.add(code_returnt()); } - wrapper_body.then_case()=init_body; - return wrapper_body; + return function_body; } /// Create static initializer wrappers for all classes that need them. diff --git a/src/java_bytecode/java_static_initializers.h b/src/java_bytecode/java_static_initializers.h index 992e9b6425b..1827acf25ce 100644 --- a/src/java_bytecode/java_static_initializers.h +++ b/src/java_bytecode/java_static_initializers.h @@ -27,7 +27,8 @@ void create_static_initializer_wrappers( synthetic_methods_mapt &synthetic_methods); codet get_clinit_wrapper_body( - const irep_idt &function_id, const symbol_table_baset &symbol_table); + const irep_idt &function_id, + symbol_table_baset &symbol_table); class stub_global_initializer_factoryt { From 4c7b646ef46672bbed1f955ee8cce8863a9efc30 Mon Sep 17 00:00:00 2001 From: Kurt Degiorgio Date: Wed, 2 May 2018 14:34:51 +0100 Subject: [PATCH 93/93] Added new cmd option to jbmc, 'java-threading' Setting this option will enable support for analysing multi-threaded java programs. For now, this means that a thread-safe version of clinit_wrapper is generated. This was made opt-in instead of opt-out as the inclusion of thread-safe clinit wrapper has negative implications for performance. Commit also adds appropriate regression tests that use this flag to test the resulting modifications to the clinit_wrapper --- regression/cbmc-java/static_init1/test1.desc | 8 + regression/cbmc-java/static_init2/test1.desc | 8 + .../cbmc-java/static_init_order/test3.desc | 7 + .../cbmc-java/static_init_order/test4.desc | 7 + src/java_bytecode/java_bytecode_language.cpp | 14 +- src/java_bytecode/java_bytecode_language.h | 1 + .../java_static_initializers.cpp | 209 +++++++++++++----- src/java_bytecode/java_static_initializers.h | 7 +- src/jbmc/jbmc_parse_options.cpp | 1 + src/jbmc/jbmc_parse_options.h | 1 + 10 files changed, 209 insertions(+), 54 deletions(-) create mode 100644 regression/cbmc-java/static_init1/test1.desc create mode 100644 regression/cbmc-java/static_init2/test1.desc create mode 100644 regression/cbmc-java/static_init_order/test3.desc create mode 100644 regression/cbmc-java/static_init_order/test4.desc diff --git a/regression/cbmc-java/static_init1/test1.desc b/regression/cbmc-java/static_init1/test1.desc new file mode 100644 index 00000000000..8bc396cff4d --- /dev/null +++ b/regression/cbmc-java/static_init1/test1.desc @@ -0,0 +1,8 @@ +CORE +static_init.class +--function static_init.main --java-threading +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/static_init2/test1.desc b/regression/cbmc-java/static_init2/test1.desc new file mode 100644 index 00000000000..8bc396cff4d --- /dev/null +++ b/regression/cbmc-java/static_init2/test1.desc @@ -0,0 +1,8 @@ +CORE +static_init.class +--function static_init.main --java-threading +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- +^warning: ignoring diff --git a/regression/cbmc-java/static_init_order/test3.desc b/regression/cbmc-java/static_init_order/test3.desc new file mode 100644 index 00000000000..6ec4686fa57 --- /dev/null +++ b/regression/cbmc-java/static_init_order/test3.desc @@ -0,0 +1,7 @@ +CORE +static_init_order.class +--function static_init_order.test1 --trace --java-threading +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/cbmc-java/static_init_order/test4.desc b/regression/cbmc-java/static_init_order/test4.desc new file mode 100644 index 00000000000..d008222606e --- /dev/null +++ b/regression/cbmc-java/static_init_order/test4.desc @@ -0,0 +1,7 @@ +CORE +static_init_order.class +--function static_init_order.test2 --java-threading +^EXIT=10$ +^SIGNAL=0$ +^VERIFICATION FAILED$ +-- diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp index cfcb797cc40..72deab72194 100644 --- a/src/java_bytecode/java_bytecode_language.cpp +++ b/src/java_bytecode/java_bytecode_language.cpp @@ -69,6 +69,11 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd) else lazy_methods_mode=LAZY_METHODS_MODE_EAGER; + if(cmd.isset("java-threading")) + threading_support = true; + else + threading_support = false; + if(cmd.isset("java-throw-runtime-exceptions")) { throw_runtime_exceptions = true; @@ -701,7 +706,8 @@ bool java_bytecode_languaget::typecheck( // For each class that will require a static initializer wrapper, create a // function named package.classname::clinit_wrapper, and a corresponding // global tracking whether it has run or not: - create_static_initializer_wrappers(symbol_table, synthetic_methods); + create_static_initializer_wrappers( + symbol_table, synthetic_methods, threading_support); // Now incrementally elaborate methods // that are reachable from this entry point. @@ -961,7 +967,11 @@ bool java_bytecode_languaget::convert_single_method( switch(synthetic_method_it->second) { case synthetic_method_typet::STATIC_INITIALIZER_WRAPPER: - symbol.value = get_clinit_wrapper_body(function_id, symbol_table); + if(threading_support) + symbol.value = get_thread_safe_clinit_wrapper_body( + function_id, symbol_table); + else + symbol.value = get_clinit_wrapper_body(function_id, symbol_table); break; case synthetic_method_typet::STUB_CLASS_STATIC_INITIALIZER: symbol.value = diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h index bb3912fa150..29c347fe227 100644 --- a/src/java_bytecode/java_bytecode_language.h +++ b/src/java_bytecode/java_bytecode_language.h @@ -159,6 +159,7 @@ class java_bytecode_languaget:public languaget irep_idt main_class; std::vector main_jar_classes; java_class_loadert java_class_loader; + bool threading_support; bool assume_inputs_non_null; // assume inputs variables to be non-null object_factory_parameterst object_factory_parameters; size_t max_user_array_length; // max size for user code created arrays diff --git a/src/java_bytecode/java_static_initializers.cpp b/src/java_bytecode/java_static_initializers.cpp index c3721978606..b001bb26001 100644 --- a/src/java_bytecode/java_static_initializers.cpp +++ b/src/java_bytecode/java_static_initializers.cpp @@ -17,7 +17,8 @@ Author: Chris Smowton, chris.smowton@diffblue.com #include /// The three states in which a `` method for a class can be before, -/// after, and during static class initialization. +/// after, and during static class initialization. These states are only used +/// when the thread safe version of the clinit wrapper is generated. /// /// According to the JVM Spec document (section 5.5), the JVM needs to /// maintain, for every class initializer, a state indicating whether the @@ -33,7 +34,9 @@ Author: Chris Smowton, chris.smowton@diffblue.com /// class is ready to be used, or it has errored" /// /// The last state corresponds to a fusion of the two original states "ready -/// for use" and "initialization error". +/// for use" and "initialization error". The basis for fusing these states is +/// that for simplification reasons both implementations of the clinit wrapper +/// do not handle exceptions, hence the error state is not possible. enum class clinit_statest { NOT_INIT, @@ -98,6 +101,15 @@ static symbolt add_new_symbol( return new_symbol; } +/// Get name of the static-initialization-already-done global variable for a +/// given class. +/// \param class_name: class symbol name +/// \return static initializer wrapper-already run global name +static irep_idt clinit_already_run_variable_name(const irep_idt &class_name) +{ + return id2string(class_name) + "::clinit_already_run"; +} + /// Get name of the real static initializer for a given class. Doesn't check /// if a static initializer actually exists. /// \param class_name: class symbol name @@ -165,6 +177,40 @@ gen_clinit_eqexpr(const exprt &expr, const clinit_statest state) return equal_exprt(expr, init_s); } +/// Generates codet that iterates through the base types of the class specified +/// by class_name, C, and recursively adds calls to their clinit wrapper. +/// Finally a call to the clinint wrapper of C is made. +/// \param symbol_table: symbol table +/// \param class_name: name of the class to generate clinit wrapper calls for +/// \param [out] init_body: appended with calls to clinit wrapper +static void clinit_wrapper_do_recursive_calls( + const symbol_tablet &symbol_table, + const irep_idt &class_name, + code_blockt &init_body) +{ + const symbolt &class_symbol = symbol_table.lookup_ref(class_name); + for(const auto &base : to_class_type(class_symbol.type).bases()) + { + const auto base_name = to_symbol_type(base.type()).get_identifier(); + irep_idt base_init_routine = clinit_wrapper_name(base_name); + auto findit = symbol_table.symbols.find(base_init_routine); + if(findit == symbol_table.symbols.end()) + continue; + code_function_callt call_base; + call_base.function() = findit->second.symbol_expr(); + init_body.move_to_operands(call_base); + } + + const irep_idt &real_clinit_name = clinit_function_name(class_name); + auto find_sym_it = symbol_table.symbols.find(real_clinit_name); + if(find_sym_it != symbol_table.symbols.end()) + { + code_function_callt call_real_init; + call_real_init.function() = find_sym_it->second.symbol_expr(); + init_body.move_to_operands(call_real_init); + } +} + /// Checks whether a static initializer wrapper is needed for a given class, /// i.e. if the given class or any superclass has a static initializer. /// \param class_name: class symbol name @@ -199,32 +245,51 @@ static bool needs_clinit_wrapper( /// \param synthetic_methods: synthetic method type map. The new clinit wrapper /// symbol will be recorded, such that we get a callback to produce its body /// if and when required. +/// \param thread_safe: if true state variables required to make the +/// clinit_wrapper thread safe will be created. static void create_clinit_wrapper_symbols( const irep_idt &class_name, symbol_tablet &symbol_table, - synthetic_methods_mapt &synthetic_methods) + synthetic_methods_mapt &synthetic_methods, + const bool thread_safe) { - exprt not_init_value = from_integer( - static_cast(clinit_statest::NOT_INIT), clinit_states_type); + if(thread_safe) + { + exprt not_init_value = from_integer( + static_cast(clinit_statest::NOT_INIT), clinit_states_type); - // Create two global static synthetic "fields" for the class "id" - // these two variables hold the state of the class initialization algorithm - // across calls to the clinit_wrapper - add_new_symbol( - symbol_table, - clinit_state_var_name(class_name), - clinit_states_type, - not_init_value, - false, - true); + // Create two global static synthetic "fields" for the class "id" + // these two variables hold the state of the class initialization algorithm + // across calls to the clinit_wrapper + add_new_symbol( + symbol_table, + clinit_state_var_name(class_name), + clinit_states_type, + not_init_value, + false, + true); - add_new_symbol( - symbol_table, - clinit_thread_local_state_var_name(class_name), - clinit_states_type, - not_init_value, - true, - true); + add_new_symbol( + symbol_table, + clinit_thread_local_state_var_name(class_name), + clinit_states_type, + not_init_value, + true, + true); + } + else + { + const irep_idt &already_run_name = + clinit_already_run_variable_name(class_name); + + add_new_symbol( + symbol_table, + already_run_name, + bool_typet(), + false_exprt(), + false, + true); + } // Create symbol for the "clinit_wrapper" symbolt wrapper_method_symbol; @@ -254,6 +319,8 @@ static void create_clinit_wrapper_symbols( "clinit wrapper"); } +/// Thread safe version of the static initialiser. +/// /// Produces the static initialiser wrapper body for the given function. This /// static initializer implements (a simplification of) the algorithm defined /// in Section 5.5 of the JVM Specs. This function, or wrapper, checks whether @@ -319,7 +386,7 @@ static void create_clinit_wrapper_symbols( /// name created by `create_clinit_wrapper_symbols`) /// \param symbol_table: global symbol table /// \return the body of the static initialiser wrapper -codet get_clinit_wrapper_body( +codet get_thread_safe_clinit_wrapper_body( const irep_idt &function_id, symbol_table_baset &symbol_table) { @@ -470,34 +537,11 @@ codet get_clinit_wrapper_body( // // java::C::(); // - code_blockt init_body; { - // iterate through the base types and add recursive calls to the - // clinit_wrapper() - const symbolt &class_symbol = symbol_table.lookup_ref(class_name); - for(const auto &base : to_class_type(class_symbol.type).bases()) - { - const auto base_name = to_symbol_type(base.type()).get_identifier(); - irep_idt base_init_routine = clinit_wrapper_name(base_name); - auto findit = symbol_table.symbols.find(base_init_routine); - if(findit == symbol_table.symbols.end()) - continue; - code_function_callt call_base; - call_base.function() = findit->second.symbol_expr(); - init_body.move_to_operands(call_base); - } - - // call java::C::(), if the class has one static initializer - const irep_idt &real_clinit_name = clinit_function_name(class_name); - auto find_sym_it = symbol_table.symbols.find(real_clinit_name); - if(find_sym_it != symbol_table.symbols.end()) - { - code_function_callt call_real_init; - call_real_init.function() = find_sym_it->second.symbol_expr(); - init_body.move_to_operands(call_real_init); - } + code_blockt init_body; + clinit_wrapper_do_recursive_calls(symbol_table, class_name, init_body); + function_body.append(init_body); } - function_body.append(init_body); // ATOMIC_START // C::__CPROVER_PREFIX_clinit_state = INIT_COMPLETE; @@ -516,14 +560,77 @@ codet get_clinit_wrapper_body( return function_body; } +/// Produces the static initialiser wrapper body for the given function. +/// Note: this version of the clinit wrapper is not thread safe. +/// \param function_id: clinit wrapper function id (the wrapper_method_symbol +/// name created by `create_clinit_wrapper_symbols`) +/// \param symbol_table: global symbol table +/// \return the body of the static initialiser wrapper/ +codet get_clinit_wrapper_body( + const irep_idt &function_id, + symbol_table_baset &symbol_table) +{ + // Assume that class C extends class C' and implements interfaces + // I1, ..., In. We now create the following function (possibly recursively + // creating the clinit_wrapper functions for C' and I1, ..., In): + // + // java::C::clinit_wrapper() + // { + // if (java::C::clinit_already_run == false) + // { + // java::C::clinit_already_run = true; // before recursive calls! + // + // java::C'::clinit_wrapper(); + // java::I1::clinit_wrapper(); + // java::I2::clinit_wrapper(); + // // ... + // java::In::clinit_wrapper(); + // + // java::C::(); + // } + // } + const symbolt &wrapper_method_symbol = symbol_table.lookup_ref(function_id); + irep_idt class_name = wrapper_method_symbol.type.get(ID_C_class); + INVARIANT( + !class_name.empty(), "wrapper function should be annotated with its class"); + + const symbolt &already_run_symbol = + symbol_table.lookup_ref(clinit_already_run_variable_name(class_name)); + + equal_exprt check_already_run( + already_run_symbol.symbol_expr(), + false_exprt()); + + // the entire body of the function is an if-then-else + code_ifthenelset wrapper_body; + + // add the condition to the if + wrapper_body.cond() = check_already_run; + + // add the "already-run = false" statement + code_blockt init_body; + code_assignt set_already_run(already_run_symbol.symbol_expr(), true_exprt()); + init_body.move_to_operands(set_already_run); + + clinit_wrapper_do_recursive_calls(symbol_table, class_name, init_body); + + wrapper_body.then_case() = init_body; + + return wrapper_body; +} + + /// Create static initializer wrappers for all classes that need them. /// \param symbol_table: global symbol table /// \param synthetic_methods: synthetic methods map. Will be extended noting /// that any wrapper belongs to this code, and so `get_clinit_wrapper_body` /// should be used to produce the method body when required. +/// \param thread_safe: if true state variables required to make the +/// clinit_wrapper thread safe will be created. void create_static_initializer_wrappers( symbol_tablet &symbol_table, - synthetic_methods_mapt &synthetic_methods) + synthetic_methods_mapt &synthetic_methods, + const bool thread_safe) { // Top-sort the class hierarchy, such that we visit parents before children, // and can so identify parents that need static initialisation by whether we @@ -539,7 +646,7 @@ void create_static_initializer_wrappers( if(needs_clinit_wrapper(class_identifier, symbol_table)) { create_clinit_wrapper_symbols( - class_identifier, symbol_table, synthetic_methods); + class_identifier, symbol_table, synthetic_methods, thread_safe); } } } diff --git a/src/java_bytecode/java_static_initializers.h b/src/java_bytecode/java_static_initializers.h index 1827acf25ce..f5f965a31b9 100644 --- a/src/java_bytecode/java_static_initializers.h +++ b/src/java_bytecode/java_static_initializers.h @@ -24,7 +24,12 @@ bool is_clinit_wrapper_function(const irep_idt &function_id); void create_static_initializer_wrappers( symbol_tablet &symbol_table, - synthetic_methods_mapt &synthetic_methods); + synthetic_methods_mapt &synthetic_methods, + bool thread_safe); + +codet get_thread_safe_clinit_wrapper_body( + const irep_idt &function_id, + symbol_table_baset &symbol_table); codet get_clinit_wrapper_body( const irep_idt &function_id, diff --git a/src/jbmc/jbmc_parse_options.cpp b/src/jbmc/jbmc_parse_options.cpp index 031d7aec587..9766aa399f1 100644 --- a/src/jbmc/jbmc_parse_options.cpp +++ b/src/jbmc/jbmc_parse_options.cpp @@ -1050,6 +1050,7 @@ void jbmc_parse_optionst::help() JAVA_BYTECODE_LANGUAGE_OPTIONS_HELP // This one is handled by jbmc_parse_options not by the Java frontend, // hence its presence here: + " --java-threading enable experimental support for java multi-threading\n"// NOLINT(*) " --java-unwind-enum-static try to unwind loops in static initialization of enums\n" // NOLINT(*) // Currently only supported in the JBMC frontend: " --symex-driven-lazy-loading only load functions when first entered by symbolic execution\n" // NOLINT(*) diff --git a/src/jbmc/jbmc_parse_options.h b/src/jbmc/jbmc_parse_options.h index 32f7e269465..4bc76174737 100644 --- a/src/jbmc/jbmc_parse_options.h +++ b/src/jbmc/jbmc_parse_options.h @@ -74,6 +74,7 @@ class optionst; JAVA_BYTECODE_LANGUAGE_OPTIONS \ "(java-unwind-enum-static)" \ "(localize-faults)(localize-faults-method):" \ + "(java-threading)" \ OPT_GOTO_TRACE \ "(symex-driven-lazy-loading)" // clang-format on