diff --git a/.travis.yml b/.travis.yml index d74ec93f7e3..54078b93f76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,30 +7,44 @@ matrix: - os: linux sudo: required compiler: gcc + cache: ccache services: - docker before_install: - - docker pull diffblue/cbmc-builder:alpine + - docker pull diffblue/cbmc-builder:alpine-0.0.1 env: - - PRE_COMMAND="docker run -v ${TRAVIS_BUILD_DIR}:/cbmc diffblue/cbmc-builder:alpine" - - COMPILER=g++ + - PRE_COMMAND="docker run -v ${TRAVIS_BUILD_DIR}:/cbmc -v ${HOME}/.ccache:/root/.ccache diffblue/cbmc-builder:alpine-0.0.1" + - COMPILER="ccache g++" # OS X using g++ - os: osx sudo: false compiler: gcc + cache: ccache + before_install: + #we create symlink to non-ccache gcc, to be used in tests + - mkdir bin ; ln -s /usr/bin/gcc bin/gcc + - brew install ccache + - export PATH=/usr/local/opt/ccache/libexec:$PATH env: COMPILER=g++ # OS X using clang++ - os: osx sudo: false compiler: clang - env: COMPILER=clang++ + cache: ccache + before_install: + - brew install ccache + - export PATH=/usr/local/opt/ccache/libexec:$PATH + env: + - COMPILER="ccache clang++ -Qunused-arguments -fcolor-diagnostics" + - CCACHE_CPP2=yes # Ubuntu Linux with glibc using g++-5 - os: linux sudo: false compiler: gcc + cache: ccache addons: apt: sources: @@ -42,12 +56,34 @@ matrix: before_install: - mkdir bin ; ln -s /usr/bin/gcc-5 bin/gcc # env: COMPILER=g++-5 SAN_FLAGS="-fsanitize=undefined -fno-sanitize-recover -fno-omit-frame-pointer" - env: COMPILER=g++-5 + env: COMPILER="g++-5" + + # Ubuntu Linux with glibc using g++-5, debug mode + - os: linux + sudo: false + compiler: gcc + cache: ccache + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - libwww-perl + - g++-5 + - libubsan0 + before_install: + - mkdir bin ; ln -s /usr/bin/gcc-5 bin/gcc + # env: COMPILER=g++-5 SAN_FLAGS="-fsanitize=undefined -fno-sanitize-recover -fno-omit-frame-pointer" + env: + - COMPILER="g++-5" + - EXTRA_CXXFLAGS="-DDEBUG" + script: echo "Not running any tests for a debug build." # Ubuntu Linux with glibc using clang++-3.7 - os: linux sudo: false compiler: clang + cache: ccache addons: apt: sources: @@ -60,19 +96,60 @@ matrix: - libubsan0 before_install: - mkdir bin ; ln -s /usr/bin/clang-3.7 bin/gcc + - export CCACHE_CPP2=yes # env: COMPILER=clang++-3.7 SAN_FLAGS="-fsanitize=undefined -fno-sanitize-recover=undefined,integer -fno-omit-frame-pointer" - env: COMPILER=clang++-3.7 + env: + - COMPILER="ccache clang++-3.7 -Qunused-arguments -fcolor-diagnostics" + - CCACHE_CPP2=yes + # Ubuntu Linux with glibc using clang++-3.7, debug mode + - os: linux + sudo: false + compiler: clang + cache: ccache + addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.7 + packages: + - libwww-perl + - clang-3.7 + - libstdc++-5-dev + - libubsan0 + before_install: + - mkdir bin ; ln -s /usr/bin/clang-3.7 bin/gcc + - export CCACHE_CPP2=yes + # env: COMPILER=clang++-3.7 SAN_FLAGS="-fsanitize=undefined -fno-sanitize-recover=undefined,integer -fno-omit-frame-pointer" + env: + - COMPILER="ccache clang++-3.7 -Qunused-arguments -fcolor-diagnostics" + - CCACHE_CPP2=yes + - EXTRA_CXXFLAGS="-DDEBUG" + script: echo "Not running any tests for a debug build." + + - env: NAME="CPP-LINT" + install: + script: scripts/travis_lint.sh + before_cache: + + allow_failures: - env: NAME="CPP-LINT" - script: scripts/travis_lint.sh || true + install: + script: scripts/travis_lint.sh + before_cache: + +install: + - COMMAND="make -C src minisat2-download" && + eval ${PRE_COMMAND} ${COMMAND} + - COMMAND="make -C src CXX=\"$COMPILER\" CXXFLAGS=\"-Wall -O2 -g -Werror -Wno-deprecated-register -pedantic -Wno-sign-compare $EXTRA_CXXFLAGS\" -j2" && + eval ${PRE_COMMAND} ${COMMAND} + - COMMAND="make -C src CXX=\"$COMPILER\" CXXFLAGS=\"$FLAGS $EXTRA_CXXFLAGS\" -j2 cegis.dir clobber.dir memory-models.dir musketeer.dir" && + eval ${PRE_COMMAND} ${COMMAND} script: - - if [ -L bin/gcc ] ; then export PATH=$PWD/bin:$PATH ; fi ; - COMMAND="make -C src minisat2-download" && - eval ${PRE_COMMAND} ${COMMAND} && - COMMAND="make -C src CXX=$COMPILER CXXFLAGS=\"-Wall -O2 -g -Werror -Wno-deprecated-register -pedantic -Wno-sign-compare\" -j2" && - eval ${PRE_COMMAND} ${COMMAND} && + - if [ -e bin/gcc ] ; then export PATH=$PWD/bin:$PATH ; fi ; COMMAND="env UBSAN_OPTIONS=print_stacktrace=1 make -C regression test" && - eval ${PRE_COMMAND} ${COMMAND} && - COMMAND="make -C src CXX=$COMPILER CXXFLAGS=$FLAGS -j2 cegis.dir clobber.dir memory-models.dir musketeer.dir" && eval ${PRE_COMMAND} ${COMMAND} + +before_cache: + - ccache -s diff --git a/CHANGELOG b/CHANGELOG index ba9ceda5549..1718d32243d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,14 @@ +5.8 +=== + +* GOTO-INSTRUMENT: --reachability-slice can be used with --property to slice + down to a single property only. +* GOTO-INSTRUMENT: New option --list-calls-args +* GOTO-INSTRUMENT: New option --print-path-lenghts +* GOTO-ANALYZER: New option --unreachable-functions, --reachable-functions +* GOTO-INSTRUMENT: New option --undefined-function-is-assume-false + + 5.7 === @@ -20,6 +31,9 @@ * GOTO-CC: GCC-style error/warning messages * GOTO-CC: New options --native-compiler and --native-linker to select the compiler/linker to be used when building combined native/goto object files. +* CBMC, SYMEX, GOTO-INSTRUMENT: New option --drop-unused-functions. Removed + ambiguous --show-reachable-properties. +* CBMC: New option --no-built-in-assertions 5.6 diff --git a/COMPILING b/COMPILING index cfbb056c2e0..7cbdfcaab13 100644 --- a/COMPILING +++ b/COMPILING @@ -44,12 +44,18 @@ We assume that you have a Debian/Ubuntu or Red Hat-like distribution. git clone https://github.com/diffblue/cbmc cbmc-git -2) On Debian/Ubuntu, do +2) On Debian, do cd cbmc-git/src make minisat2-download make CXX=g++-6 + On Ubuntu, or other distributions with recent g++, do + + cd cbmc-git/src + make minisat2-download + make + On Redhat/Fedora etc., do cd cbmc-git/src @@ -64,7 +70,7 @@ COMPILATION ON SOLARIS 11 1) As root, get the necessary development tools: pkg install system/header developer/lexer/flex developer/parser/bison developer/versioning/git - pkg install --accept developer/gcc-5 + pkg install --accept developer/gcc/gcc-c++-5 2) As a user, get the CBMC source via @@ -86,9 +92,6 @@ COMPILATION ON SOLARIS 11 export LD_LIBRARY_PATH=/usr/gcc/4.9/lib - Do not attempt to compile with gcc-45 that comes with Solaris 11. - It will mis-optimize MiniSat2. - COMPILATION ON FREEBSD 11 ------------------------- @@ -163,23 +166,21 @@ Follow these instructions: The patch removes the dependency on zlib and prevents a problem with a header file that is often unavailable on Windows. -2) Adjust src/config.inc for the paths to item 1). - -3A) To compile with Cygwin, install the mingw compilers, and adjust +2A) To compile with Cygwin, install the mingw compilers, and adjust the second line of config.inc to say BUILD_ENV = MinGW -3B) To compile with Visual Studio, make sure you have at least Visual +2B) To compile with Visual Studio, make sure you have at least Visual Studio version 12 (2013), and adjust the second line of config.inc to say BUILD_ENV = MSVC - Open the Visual Studio Command prompt, and then run the make.exe - from Cygwin from in there. + Open the Visual Studio Command prompt, and then bash.exe -login from + Cygwin from in there. + +3) Type cd src; make - that should do it. -4) Type cd src; make - that should do it. - Note that "nmake" is not expected to work. Use "make". (Optional) A Visual Studio project file can be generated with the script "generate_vcxproj" that is in the subdirectory "scripts". The project file diff --git a/doc/html-manual/cover.shtml b/doc/html-manual/cover.shtml index 45a3fb82143..5e3bfaffad8 100644 --- a/doc/html-manual/cover.shtml +++ b/doc/html-manual/cover.shtml @@ -149,7 +149,7 @@ To demonstrate the automatic test suite generation in CBMC, we call the following command and we are going to explain the command line options one by one.

-
cbmc pid.c --cover mcdc --unwind 6 --trace --xml-ui
+
cbmc pid.c --cover mcdc --unwind 6 --xml-ui
 

@@ -173,11 +173,11 @@ pprz >= (float)0 && pprz <= (float)(16 * 600) id="climb_pid_run.coverage.3"

The "id" of each coverage goal is automatically assigned by CBMC. For every -coverage goal, a trace (if there exists) of the program execution that -satisfies such a goal is printed out in XML format, as the parameters ---trace --xml-ui are given. Multiple coverage goals can share a -trace, when the corresponding execution of the program satisfies all these -goals at the same time. Each trace corresponds to a test case. +coverage goal, a test suite (if there exists) that +satisfies such a goal is printed out in XML format, as the parameter +--xml-ui is given. Multiple coverage goals can share a +test suite, when the corresponding execution of the program satisfies all these +goals at the same time.

@@ -185,6 +185,10 @@ In the end, the following test suites are automatically generated for testing th A test suite consists of a sequence of input parameters that are passed to the PID function climb_pid_run at each loop iteration. For example, Test 1 covers the MC/DC goal with id="climb_pid_run.coverage.1". +The complete output from CBMC is in +pid_test_suites.xml, where every test suite and the coverage goals it is for +are clearly described. +

Test suite:
 Test 1. 
   (iteration 1) desired_climb=-1.000000f, estimator_z_dot=1.000000f
diff --git a/doc/html-manual/pid_test_suites.xml b/doc/html-manual/pid_test_suites.xml
new file mode 100644
index 00000000000..014fea12294
--- /dev/null
+++ b/doc/html-manual/pid_test_suites.xml
@@ -0,0 +1,500 @@
+
+
+CBMC 5.5
+
+  CBMC version 5.5 64-bit x86_64 macos
+
+
+
+  Parsing pid.c
+
+
+
+  Converting
+
+
+
+  Type-checking pid
+
+
+
+  
+  function `nondet_float' is not declared
+
+
+
+  Generating GOTO Program
+
+
+
+  Adding CPROVER library (x86_64)
+
+
+
+  Removal of function pointers and virtual functions
+
+
+
+  Partial Inlining
+
+
+
+  Generic Property Instrumentation
+
+
+criterion: mcdc
+
+
+  Instrumenting coverage goals
+
+
+
+  Starting Bounded Model Checking
+
+
+
+  Unwinding loop main.0 iteration 1 (6 max) file pid.c line 56 function main thread 0
+
+
+
+  Unwinding loop main.0 iteration 2 (6 max) file pid.c line 56 function main thread 0
+
+
+
+  Unwinding loop main.0 iteration 3 (6 max) file pid.c line 56 function main thread 0
+
+
+
+  Unwinding loop main.0 iteration 4 (6 max) file pid.c line 56 function main thread 0
+
+
+
+  Unwinding loop main.0 iteration 5 (6 max) file pid.c line 56 function main thread 0
+
+
+
+  Not unwinding loop main.0 iteration 6 (6 max) file pid.c line 56 function main thread 0
+
+
+
+  size of program expression: 416 steps
+
+
+
+  Generated 114 VCC(s), 108 remaining after simplification
+
+
+
+  Passing problem to propositional reduction
+
+
+
+  converting SSA
+
+
+
+  Aiming to cover 19 goal(s)
+
+
+
+  Running propositional reduction
+
+
+
+  Post-processing
+
+
+
+  Solving with MiniSAT 2.2.1 with simplifier
+
+
+
+  131818 variables, 553801 clauses
+
+
+
+  SAT checker: instance is SATISFIABLE
+
+
+
+  Covered decision/condition `1 != 0' true
+
+
+
+  Solving with MiniSAT 2.2.1 with simplifier
+
+
+
+  131818 variables, 395675 clauses
+
+
+
+  SAT checker: instance is SATISFIABLE
+
+
+
+  Covered MC/DC independence condition `!(pprz >= (float)0) && pprz <= (float)(16 * 600)'
+
+
+
+  Covered decision `pprz >= (float)0 && pprz <= (float)(16 * 600)' false
+
+
+
+  Covered condition `pprz >= (float)0' false
+
+
+
+  Covered decision/condition `pprz > (float)(16 * 600)' false
+
+
+
+  Covered condition `pprz <= (float)(16 * 600)' true
+
+
+
+  Covered decision/condition `desired_climb > (float)0' false
+
+
+
+  Covered decision/condition `climb_sum_err > (float)10' false
+
+
+
+  Covered decision/condition `climb_sum_err < (float)-10' false
+
+
+
+  Solving with MiniSAT 2.2.1 with simplifier
+
+
+
+  131818 variables, 393279 clauses
+
+
+
+  SAT checker: instance is SATISFIABLE
+
+
+
+  Covered MC/DC independence condition `pprz >= (float)0 && !(pprz <= (float)(16 * 600))'
+
+
+
+  Covered condition `pprz >= (float)0' true
+
+
+
+  Covered decision/condition `pprz > (float)(16 * 600)' true
+
+
+
+  Covered condition `pprz <= (float)(16 * 600)' false
+
+
+
+  Covered decision/condition `desired_climb > (float)0' true
+
+
+
+  Solving with MiniSAT 2.2.1 with simplifier
+
+
+
+  131818 variables, 391285 clauses
+
+
+
+  SAT checker: instance is SATISFIABLE
+
+
+
+  Covered MC/DC independence condition `pprz >= (float)0 && pprz <= (float)(16 * 600)'
+
+
+
+  Covered decision `pprz >= (float)0 && pprz <= (float)(16 * 600)' true
+
+
+
+  Solving with MiniSAT 2.2.1 with simplifier
+
+
+
+  131818 variables, 390122 clauses
+
+
+
+  SAT checker: instance is SATISFIABLE
+
+
+
+  Covered decision/condition `climb_sum_err < (float)-10' true
+
+
+
+  Solving with MiniSAT 2.2.1 with simplifier
+
+
+
+  131818 variables, 390121 clauses
+
+
+
+  SAT checker: instance is SATISFIABLE
+
+
+
+  Covered decision/condition `climb_sum_err > (float)10' true
+
+
+
+  Solving with MiniSAT 2.2.1 with simplifier
+
+
+
+  131818 variables, 387493 clauses
+
+
+
+  SAT checker inconsistent: instance is UNSATISFIABLE
+
+
+
+  Runtime decision procedure: 3.806s
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+
+
+
+  
+  
+
+
+
+  
+    
+      -1.000000
+    
+    
+      1.000000
+    
+  
+  
+  
+  
+  
+  
+  
+  
+  
+
+
+
+  
+    
+      -1.000000
+    
+    
+      1.000000
+    
+    
+      1.000000
+    
+    
+      -1.000000
+    
+  
+  
+  
+  
+  
+  
+
+
+
+  
+    
+      0.000000
+    
+    
+      -1.000000
+    
+    
+      1.000000
+    
+    
+      -1.000000
+    
+  
+  
+  
+
+
+
+  
+    
+      1.000000
+    
+    
+      -1.000000
+    
+    
+      1.000000
+    
+    
+      -1.000000
+    
+    
+      1.000000
+    
+    
+      -1.000000
+    
+    
+      1.000000
+    
+    
+      -1.000000
+    
+    
+      0.000000
+    
+    
+      -1.000000
+    
+    
+      1.000000
+    
+    
+      -1.000000
+    
+  
+  
+
+
+
+  
+    
+      -1.000000
+    
+    
+      1.000000
+    
+    
+      -1.000000
+    
+    
+      1.000000
+    
+    
+      -1.000000
+    
+    
+      1.000000
+    
+    
+      -1.000000
+    
+    
+      1.000000
+    
+    
+      -1.000000
+    
+    
+      1.000000
+    
+    
+      -1.000000
+    
+    
+      1.000000
+    
+  
+  
+
+
+
+  ** 18 of 19 covered (94.7%)
+
+
+
+  ** Used 7 iterations
+
+
+
diff --git a/regression/Makefile b/regression/Makefile
index 5c59fd6e34c..296f583cc5e 100644
--- a/regression/Makefile
+++ b/regression/Makefile
@@ -5,6 +5,7 @@ DIRS = ansi-c \
        cbmc-java \
        goto-analyzer \
        goto-instrument \
+       goto-instrument-typedef \
        test-script \
        # Empty last line
 
diff --git a/regression/acceleration/Makefile b/regression/acceleration/Makefile
index 396fa63f22d..805ebaec1e8 100644
--- a/regression/acceleration/Makefile
+++ b/regression/acceleration/Makefile
@@ -14,5 +14,5 @@ show:
 	done;
 
 clean:
-	rm -f tests.log
-	rm -f */main.out
+	$(RM) tests.log
+	$(RM) */main.out
diff --git a/regression/ansi-c/Makefile b/regression/ansi-c/Makefile
index b03e120015b..87af55e3306 100644
--- a/regression/ansi-c/Makefile
+++ b/regression/ansi-c/Makefile
@@ -18,3 +18,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/ansi-c/function_return1/test.desc b/regression/ansi-c/function_return1/test.desc
index 78396740555..f49480a607f 100644
--- a/regression/ansi-c/function_return1/test.desc
+++ b/regression/ansi-c/function_return1/test.desc
@@ -3,7 +3,6 @@ main.c
 --verbosity 2
 ^main.c:3:1: warning: function has return void but a return statement returning signed int$
 ^SIGNAL=0$
-
 --
 ^warning: ignoring
 ^CONVERSION ERROR$
diff --git a/regression/ansi-c/gcc_types_compatible_p1/main.c b/regression/ansi-c/gcc_types_compatible_p1/main.c
index 403596c4276..4f327d51085 100644
--- a/regression/ansi-c/gcc_types_compatible_p1/main.c
+++ b/regression/ansi-c/gcc_types_compatible_p1/main.c
@@ -7,6 +7,14 @@ double d;
 typedef enum T1 { hot, dog, poo, bear } dingos;
 typedef enum T2 { janette, laura, amanda } cranberry;
 
+typedef enum AnonEnum { jim, bob, fred } names;
+
+typedef dingos altdingos;
+typedef dingos diffdingos;
+
+typedef names altnames;
+typedef names diffnames;
+
 typedef float same1;
 typedef float same2;
 
@@ -52,6 +60,9 @@ STATIC_ASSERT(__builtin_types_compatible_p(typeof (dingos), unsigned)); // ha!
 STATIC_ASSERT(__builtin_types_compatible_p(typeof (hot), typeof (laura)));
 STATIC_ASSERT(__builtin_types_compatible_p(int[5], int[]));
 STATIC_ASSERT(__builtin_types_compatible_p(same1, same2));
+STATIC_ASSERT(__builtin_types_compatible_p(dingos, altdingos));
+STATIC_ASSERT(__builtin_types_compatible_p(diffdingos, altdingos));
+STATIC_ASSERT(__builtin_types_compatible_p(diffnames, altnames));
 STATIC_ASSERT(__builtin_types_compatible_p(typeof (hot) *, int *));
 STATIC_ASSERT(__builtin_types_compatible_p(typeof (hot), typeof (janette)));
 STATIC_ASSERT(__builtin_types_compatible_p(__int128, signed __int128));
@@ -84,7 +95,6 @@ STATIC_ASSERT(!__builtin_types_compatible_p(__float128, long double));
 STATIC_ASSERT(!__builtin_types_compatible_p(__float128, double));
 STATIC_ASSERT(!__builtin_types_compatible_p(__int128, unsigned __int128));
 #endif
-
 #endif
 
 int main(void)
diff --git a/regression/ansi-c/gcc_types_compatible_p4/main.c b/regression/ansi-c/gcc_types_compatible_p4/main.c
new file mode 100644
index 00000000000..69b84a8304b
--- /dev/null
+++ b/regression/ansi-c/gcc_types_compatible_p4/main.c
@@ -0,0 +1,27 @@
+#define STATIC_ASSERT(condition) \
+  int some_array[(condition) ? 1 : -1];
+
+typedef struct struct_tag
+{
+  int x;
+  float y;
+} struct_typedef;
+
+typedef struct struct_tag alt_typedef;
+typedef struct_typedef another_typedef;
+
+#ifdef __GNUC__
+
+
+STATIC_ASSERT(__builtin_types_compatible_p(struct struct_tag, struct_typedef));
+STATIC_ASSERT(__builtin_types_compatible_p(struct struct_tag, alt_typedef));
+STATIC_ASSERT(__builtin_types_compatible_p(struct struct_tag, another_typedef));
+STATIC_ASSERT(__builtin_types_compatible_p(struct_typedef, alt_typedef));
+STATIC_ASSERT(__builtin_types_compatible_p(struct_typedef, another_typedef));
+STATIC_ASSERT(__builtin_types_compatible_p(alt_typedef, another_typedef));
+
+#endif
+
+int main(void)
+{
+}
diff --git a/regression/ansi-c/gcc_types_compatible_p4/test.desc b/regression/ansi-c/gcc_types_compatible_p4/test.desc
new file mode 100644
index 00000000000..466da18b2b5
--- /dev/null
+++ b/regression/ansi-c/gcc_types_compatible_p4/test.desc
@@ -0,0 +1,8 @@
+CORE
+main.c
+
+^EXIT=0$
+^SIGNAL=0$
+--
+^warning: ignoring
+^CONVERSION ERROR$
diff --git a/regression/ansi-c/static_inline1/main.c b/regression/ansi-c/static_inline1/main.c
new file mode 100644
index 00000000000..ba8e8c6fb6b
--- /dev/null
+++ b/regression/ansi-c/static_inline1/main.c
@@ -0,0 +1,11 @@
+inline static int fun(int a)
+{
+    return a+1;
+}
+
+int main(int argc, char *argv[])
+{
+    fun(5);
+    return 0;
+}
+
diff --git a/regression/ansi-c/static_inline1/test.desc b/regression/ansi-c/static_inline1/test.desc
new file mode 100644
index 00000000000..5717777037a
--- /dev/null
+++ b/regression/ansi-c/static_inline1/test.desc
@@ -0,0 +1,9 @@
+KNOWNBUG
+main.c
+
+^EXIT=0$
+^SIGNAL=0$
+^VERIFICATION SUCCESSFUL$
+
+--
+^warning: ignoring
diff --git a/regression/ansi-c/static_inline2/main.c b/regression/ansi-c/static_inline2/main.c
new file mode 100644
index 00000000000..c67e498b4f5
--- /dev/null
+++ b/regression/ansi-c/static_inline2/main.c
@@ -0,0 +1,4 @@
+inline static int fun(int a)
+{
+    return a+1;
+}
diff --git a/regression/ansi-c/static_inline2/test.desc b/regression/ansi-c/static_inline2/test.desc
new file mode 100644
index 00000000000..c5c5692745d
--- /dev/null
+++ b/regression/ansi-c/static_inline2/test.desc
@@ -0,0 +1,9 @@
+KNOWNBUG
+main.c
+--function fun
+^EXIT=0$
+^SIGNAL=0$
+^VERIFICATION SUCCESSFUL$
+
+--
+^warning: ignoring
diff --git a/regression/array-refinement-with-incr/Makefile b/regression/array-refinement-with-incr/Makefile
index 579de53f6c3..67153d5df71 100644
--- a/regression/array-refinement-with-incr/Makefile
+++ b/regression/array-refinement-with-incr/Makefile
@@ -14,3 +14,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/array-refinement/Makefile b/regression/array-refinement/Makefile
index 41e06e86158..0fd2a56b6f6 100644
--- a/regression/array-refinement/Makefile
+++ b/regression/array-refinement/Makefile
@@ -14,3 +14,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/cbmc-concurrency/Makefile b/regression/cbmc-concurrency/Makefile
index f40172c17a2..bf0682a5381 100644
--- a/regression/cbmc-concurrency/Makefile
+++ b/regression/cbmc-concurrency/Makefile
@@ -12,3 +12,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/cbmc-concurrency/trace1/main.c b/regression/cbmc-concurrency/trace1/main.c
new file mode 100644
index 00000000000..7e1d3749edd
--- /dev/null
+++ b/regression/cbmc-concurrency/trace1/main.c
@@ -0,0 +1,28 @@
+// #include 
+#include 
+
+volatile unsigned x = 0, y = 0;
+volatile unsigned r1 = 0, r2 = 0;
+
+void* thr1(void* arg) {
+  x = 1;
+  r1 = y + 1;
+  return 0;
+}
+
+void* thr2(void* arg) {
+  y = 1;
+  r2 = x + 1;
+  return 0;
+}
+
+int main(){
+  // pthread_t t1, t2;
+  // pthread_create(&t1, NULL, thr1, NULL);
+  // pthread_create(&t2, NULL, thr2, NULL);
+__CPROVER_ASYNC_1: thr1(0);
+__CPROVER_ASYNC_2: thr2(0);
+  assert(r1 != 1 || r2 != 1);
+  return 0;
+}
+
diff --git a/regression/cbmc-concurrency/trace1/test.desc b/regression/cbmc-concurrency/trace1/test.desc
new file mode 100644
index 00000000000..a6f904e7a86
--- /dev/null
+++ b/regression/cbmc-concurrency/trace1/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--mm tso --trace
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
+^[[:space:]]*r2=1u \(.*\)$
+--
+^warning: ignoring
diff --git a/regression/cbmc-cover/Makefile b/regression/cbmc-cover/Makefile
index cbdd3378bac..9a14abc905f 100644
--- a/regression/cbmc-cover/Makefile
+++ b/regression/cbmc-cover/Makefile
@@ -18,3 +18,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/cbmc-cpp/Makefile b/regression/cbmc-cpp/Makefile
index f40172c17a2..bf0682a5381 100644
--- a/regression/cbmc-cpp/Makefile
+++ b/regression/cbmc-cpp/Makefile
@@ -12,3 +12,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/cbmc-from-CVS/Makefile b/regression/cbmc-from-CVS/Makefile
index f40172c17a2..bf0682a5381 100644
--- a/regression/cbmc-from-CVS/Makefile
+++ b/regression/cbmc-from-CVS/Makefile
@@ -12,3 +12,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/cbmc-incr-oneloop/Makefile b/regression/cbmc-incr-oneloop/Makefile
index 4c5b7ceffd3..00c5ea25db4 100644
--- a/regression/cbmc-incr-oneloop/Makefile
+++ b/regression/cbmc-incr-oneloop/Makefile
@@ -14,5 +14,5 @@ show:
 	done;
 
 clean:
-	@rm -f *.log
-	@(for dir in *; do rm -f $$dir/*.out; done;)
+	@$(RM) *.log
+	@(for dir in *; do $(RM) $$dir/*.out; done;)
diff --git a/regression/cbmc-incr/Makefile b/regression/cbmc-incr/Makefile
index 965ce493fc5..08b694ea9b5 100644
--- a/regression/cbmc-incr/Makefile
+++ b/regression/cbmc-incr/Makefile
@@ -17,5 +17,5 @@ show:
 	done;
 
 clean:
-	@rm -f *.log
-	@(for dir in *; do rm -f $$dir/*.out; done;)
+	@$(RM) *.log
+	@(for dir in *; do $(RM) $$dir/*.out; done;)
diff --git a/regression/cbmc-java/Makefile b/regression/cbmc-java/Makefile
index cee83cba67a..a1b44c5a948 100644
--- a/regression/cbmc-java/Makefile
+++ b/regression/cbmc-java/Makefile
@@ -18,3 +18,8 @@ show:
 			vim -o "$$dir/*.java" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/cbmc-java/classpath2/jarfile3$A.class b/regression/cbmc-java/classpath2/jarfile3$A.class
new file mode 100644
index 00000000000..22a9c4c39f9
Binary files /dev/null and b/regression/cbmc-java/classpath2/jarfile3$A.class differ
diff --git a/regression/cbmc-java/classpath2/jarfile3$B.class b/regression/cbmc-java/classpath2/jarfile3$B.class
new file mode 100644
index 00000000000..11284e5ebe1
Binary files /dev/null and b/regression/cbmc-java/classpath2/jarfile3$B.class differ
diff --git a/regression/cbmc-java/classpath2/jarfile3.class b/regression/cbmc-java/classpath2/jarfile3.class
new file mode 100644
index 00000000000..ececc4cc305
Binary files /dev/null and b/regression/cbmc-java/classpath2/jarfile3.class differ
diff --git a/regression/cbmc-java/classpath2/jarfile3.java b/regression/cbmc-java/classpath2/jarfile3.java
new file mode 100644
index 00000000000..c9c0cff46d1
--- /dev/null
+++ b/regression/cbmc-java/classpath2/jarfile3.java
@@ -0,0 +1,19 @@
+public class jarfile3
+{
+  public class A
+  {
+    int x=1;
+  }
+  public class B
+  {
+    int x=1;
+  }
+
+  void f(int i)
+  {
+    A a=new A();
+    B b=new B();
+    assert(a.x==1);
+    assert(b.x==1);
+  }
+}
diff --git a/regression/cbmc-java/classpath2/test.desc b/regression/cbmc-java/classpath2/test.desc
new file mode 100644
index 00000000000..ba3ea35b785
--- /dev/null
+++ b/regression/cbmc-java/classpath2/test.desc
@@ -0,0 +1,10 @@
+CORE
+jarfile3.class
+--function jarfile3.f --java-cp-include-files "jarfile3\.class"
+^EXIT=10$
+^SIGNAL=0$
+.*SUCCESS$
+.*FAILURE$
+^VERIFICATION FAILED
+--
+^warning: ignoring
diff --git a/regression/cbmc-java/exceptions1/test.desc b/regression/cbmc-java/exceptions1/test.desc
index 638351f4397..1405444f649 100644
--- a/regression/cbmc-java/exceptions1/test.desc
+++ b/regression/cbmc-java/exceptions1/test.desc
@@ -4,7 +4,7 @@ test.class
 ^EXIT=10$
 ^SIGNAL=0$
 ^.*assertion at file test.java line 26 function.*: FAILURE$
-\*\* 1 of 9 failed \(2 iterations\)$
+\*\* 1 of [0-9]* failed \(2 iterations\)$
 ^VERIFICATION FAILED$
 --
 ^warning: ignoring
diff --git a/regression/cbmc-java/exceptions2/test.desc b/regression/cbmc-java/exceptions2/test.desc
index 8645e5ea074..724e37b0677 100644
--- a/regression/cbmc-java/exceptions2/test.desc
+++ b/regression/cbmc-java/exceptions2/test.desc
@@ -4,7 +4,7 @@ test.class
 ^EXIT=10$
 ^SIGNAL=0$
 ^.*assertion at file test.java line 15 function.*: FAILURE$
-^\*\* 1 of 5 failed \(2 iterations\)$
+^\*\* 1 of [0-9]* failed \(2 iterations\)$
 ^VERIFICATION FAILED$
 --
 ^warning: ignoring
diff --git a/regression/cbmc-java/lazyloading3/A.class b/regression/cbmc-java/lazyloading3/A.class
index affb565d625..3c3c1f09997 100644
Binary files a/regression/cbmc-java/lazyloading3/A.class and b/regression/cbmc-java/lazyloading3/A.class differ
diff --git a/regression/cbmc-java/lazyloading3/B.class b/regression/cbmc-java/lazyloading3/B.class
index 9a4ab54d369..092984f5b11 100644
Binary files a/regression/cbmc-java/lazyloading3/B.class and b/regression/cbmc-java/lazyloading3/B.class differ
diff --git a/regression/cbmc-java/lazyloading3/C.class b/regression/cbmc-java/lazyloading3/C.class
index c249e24ace4..ba5fbcb0c55 100644
Binary files a/regression/cbmc-java/lazyloading3/C.class and b/regression/cbmc-java/lazyloading3/C.class differ
diff --git a/regression/cbmc-java/lazyloading3/D.class b/regression/cbmc-java/lazyloading3/D.class
index 7e16bd6527d..33579be8902 100644
Binary files a/regression/cbmc-java/lazyloading3/D.class and b/regression/cbmc-java/lazyloading3/D.class differ
diff --git a/regression/cbmc-java/lazyloading3/test.class b/regression/cbmc-java/lazyloading3/test.class
index 8e470f64650..5df466fc9ea 100644
Binary files a/regression/cbmc-java/lazyloading3/test.class and b/regression/cbmc-java/lazyloading3/test.class differ
diff --git a/regression/cbmc-java/lazyloading3/test.java b/regression/cbmc-java/lazyloading3/test.java
index 6d3129d1261..f69a9898472 100644
--- a/regression/cbmc-java/lazyloading3/test.java
+++ b/regression/cbmc-java/lazyloading3/test.java
@@ -5,6 +5,8 @@ public class test
 {
   public static void main(C c)
   {
+    if(c==null)
+      return;
     c.a.f();
   }
 }
diff --git a/regression/cbmc-with-incr/Makefile b/regression/cbmc-with-incr/Makefile
index 4ab60f487d0..4389f3bb8ef 100644
--- a/regression/cbmc-with-incr/Makefile
+++ b/regression/cbmc-with-incr/Makefile
@@ -14,5 +14,5 @@ show:
 	done;
 
 clean:
-	@rm -f *.log
-	@for dir in *; do rm -f $$dir/*.out; done;
+	@$(RM) *.log
+	@for dir in *; do $(RM) $$dir/*.out; done;
diff --git a/regression/cbmc/Makefile b/regression/cbmc/Makefile
index cbdd3378bac..9a14abc905f 100644
--- a/regression/cbmc/Makefile
+++ b/regression/cbmc/Makefile
@@ -18,3 +18,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/cbmc/Pointer_byte_extract9/main.c b/regression/cbmc/Pointer_byte_extract9/main.c
index 931f165c405..0b76b78021f 100644
--- a/regression/cbmc/Pointer_byte_extract9/main.c
+++ b/regression/cbmc/Pointer_byte_extract9/main.c
@@ -1,3 +1,5 @@
+#include 
+
 int main()
 {
   int N;
diff --git a/regression/cbmc/graphml_witness1/test.desc b/regression/cbmc/graphml_witness1/test.desc
index 9e7f5b42724..cb22eaba5d0 100644
--- a/regression/cbmc/graphml_witness1/test.desc
+++ b/regression/cbmc/graphml_witness1/test.desc
@@ -46,29 +46,29 @@ main.c
   
     C
     
-    
+    
       true
     
-    
+    
       main.c
       21
     
-    
-    
+    
+    
       main.c
       29
       main
     
-    
-    
+    
+    
       main.c
       15
       remove_one
     
-    
+    
       true
     
-    
+    
       main.c
       31
     
diff --git a/regression/cbmc/typedef-anon-struct1/main.c b/regression/cbmc/typedef-anon-struct1/main.c
new file mode 100644
index 00000000000..d1e7196a3b1
--- /dev/null
+++ b/regression/cbmc/typedef-anon-struct1/main.c
@@ -0,0 +1,11 @@
+
+typedef struct
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun()
+{
+  MYSTRUCT mystruct_var = {.x = 3, .y = 2.1f};
+}
diff --git a/regression/cbmc/typedef-anon-struct1/test.desc b/regression/cbmc/typedef-anon-struct1/test.desc
new file mode 100644
index 00000000000..d9d9769f677
--- /dev/null
+++ b/regression/cbmc/typedef-anon-struct1/test.desc
@@ -0,0 +1,10 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: mystruct_var\nMode\.+: C\nType\.+: MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-anon-struct2/main.c b/regression/cbmc/typedef-anon-struct2/main.c
new file mode 100644
index 00000000000..35475513f7d
--- /dev/null
+++ b/regression/cbmc/typedef-anon-struct2/main.c
@@ -0,0 +1,11 @@
+
+typedef struct
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun()
+{
+  MYSTRUCT mystruct_var  = {.x = 10, .y = 3.1f}, another_mystruct_var = {.x = 3, .y = 2.1f};
+}
diff --git a/regression/cbmc/typedef-anon-struct2/test.desc b/regression/cbmc/typedef-anon-struct2/test.desc
new file mode 100644
index 00000000000..83af4f59a9f
--- /dev/null
+++ b/regression/cbmc/typedef-anon-struct2/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: mystruct_var\nMode\.+: C\nType\.+: MYSTRUCT
+Base name\.+: another_mystruct_var\nMode\.+: C\nType\.+: MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-anon-union1/main.c b/regression/cbmc/typedef-anon-union1/main.c
new file mode 100644
index 00000000000..9322c77cb6e
--- /dev/null
+++ b/regression/cbmc/typedef-anon-union1/main.c
@@ -0,0 +1,11 @@
+
+typedef union
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun()
+{
+  MYUNION myunion_var = {.y = 2.1f};
+}
diff --git a/regression/cbmc/typedef-anon-union1/test.desc b/regression/cbmc/typedef-anon-union1/test.desc
new file mode 100644
index 00000000000..6f74f9f5574
--- /dev/null
+++ b/regression/cbmc/typedef-anon-union1/test.desc
@@ -0,0 +1,10 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: myunion_var\nMode\.+: C\nType\.+: MYUNION
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-anon-union2/main.c b/regression/cbmc/typedef-anon-union2/main.c
new file mode 100644
index 00000000000..b2dd6594432
--- /dev/null
+++ b/regression/cbmc/typedef-anon-union2/main.c
@@ -0,0 +1,11 @@
+
+typedef union
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun()
+{
+  MYUNION myunion_var = {.y = 2.1f}, another_myunion_var = {.y = 2.1f};
+}
diff --git a/regression/cbmc/typedef-anon-union2/test.desc b/regression/cbmc/typedef-anon-union2/test.desc
new file mode 100644
index 00000000000..f5242dc7ac7
--- /dev/null
+++ b/regression/cbmc/typedef-anon-union2/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: myunion_var\nMode\.+: C\nType\.+: MYUNION
+Base name\.+: another_myunion_var\nMode\.+: C\nType\.+: MYUNION
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-const-struct1/main.c b/regression/cbmc/typedef-const-struct1/main.c
new file mode 100644
index 00000000000..ab8137e82e4
--- /dev/null
+++ b/regression/cbmc/typedef-const-struct1/main.c
@@ -0,0 +1,12 @@
+
+typedef struct tag_struct_name
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun()
+{
+  const struct tag_struct_name tag_struct_var = {.x = 1, .y = 3.14f};
+  const MYSTRUCT mystruct_var = {.x = 3, .y = 2.1f};
+}
diff --git a/regression/cbmc/typedef-const-struct1/test.desc b/regression/cbmc/typedef-const-struct1/test.desc
new file mode 100644
index 00000000000..f6c2d8e4b48
--- /dev/null
+++ b/regression/cbmc/typedef-const-struct1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_struct_var\nMode\.+: C\nType\.+: const struct tag_struct_name
+Base name\.+: mystruct_var\nMode\.+: C\nType\.+: const MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-const-type1/main.c b/regression/cbmc/typedef-const-type1/main.c
new file mode 100644
index 00000000000..8cd4a4346eb
--- /dev/null
+++ b/regression/cbmc/typedef-const-type1/main.c
@@ -0,0 +1,8 @@
+
+typedef int MYINT;
+
+void fun()
+{
+  const int int_var = 3;
+  const MYINT myint_var = 5;
+}
diff --git a/regression/cbmc/typedef-const-type1/test.desc b/regression/cbmc/typedef-const-type1/test.desc
new file mode 100644
index 00000000000..0e1b67ce3da
--- /dev/null
+++ b/regression/cbmc/typedef-const-type1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_var\nMode\.+: C\nType\.+: const signed int
+Base name\.+: myint_var\nMode\.+: C\nType\.+: const MYINT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-const-union1/main.c b/regression/cbmc/typedef-const-union1/main.c
new file mode 100644
index 00000000000..b8defe635a6
--- /dev/null
+++ b/regression/cbmc/typedef-const-union1/main.c
@@ -0,0 +1,12 @@
+
+typedef union tag_union_name
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun()
+{
+  const union tag_union_name tag_union_var = {1};
+  const MYUNION myunion_var = {.y = 2.1f};
+}
diff --git a/regression/cbmc/typedef-const-union1/test.desc b/regression/cbmc/typedef-const-union1/test.desc
new file mode 100644
index 00000000000..019a6551911
--- /dev/null
+++ b/regression/cbmc/typedef-const-union1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_union_var\nMode\.+: C\nType\.+: const union tag_union_name
+Base name\.+: myunion_var\nMode\.+: C\nType\.+: const MYUNION
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-param-anon-struct1/main.c b/regression/cbmc/typedef-param-anon-struct1/main.c
new file mode 100644
index 00000000000..e8f3fb8fd7c
--- /dev/null
+++ b/regression/cbmc/typedef-param-anon-struct1/main.c
@@ -0,0 +1,11 @@
+
+typedef struct
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun(MYSTRUCT mystruct_param)
+{
+
+}
diff --git a/regression/cbmc/typedef-param-anon-struct1/test.desc b/regression/cbmc/typedef-param-anon-struct1/test.desc
new file mode 100644
index 00000000000..1d7c939008a
--- /dev/null
+++ b/regression/cbmc/typedef-param-anon-struct1/test.desc
@@ -0,0 +1,10 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: mystruct_param\nMode\.+: C\nType\.+: MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-param-anon-union1/main.c b/regression/cbmc/typedef-param-anon-union1/main.c
new file mode 100644
index 00000000000..71791d9adfc
--- /dev/null
+++ b/regression/cbmc/typedef-param-anon-union1/main.c
@@ -0,0 +1,10 @@
+
+typedef union
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun(MYUNION myunion_param)
+{
+}
diff --git a/regression/cbmc/typedef-param-anon-union1/test.desc b/regression/cbmc/typedef-param-anon-union1/test.desc
new file mode 100644
index 00000000000..34c29cefda9
--- /dev/null
+++ b/regression/cbmc/typedef-param-anon-union1/test.desc
@@ -0,0 +1,10 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: myunion_param\nMode\.+: C\nType\.+: MYUNION
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-param-struct1/main.c b/regression/cbmc/typedef-param-struct1/main.c
new file mode 100644
index 00000000000..a358c15a030
--- /dev/null
+++ b/regression/cbmc/typedef-param-struct1/main.c
@@ -0,0 +1,10 @@
+
+typedef struct tag_struct_name
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun(struct tag_struct_name tag_struct_param, MYSTRUCT mystruct_param)
+{
+}
diff --git a/regression/cbmc/typedef-param-struct1/test.desc b/regression/cbmc/typedef-param-struct1/test.desc
new file mode 100644
index 00000000000..ad0d23ed7a9
--- /dev/null
+++ b/regression/cbmc/typedef-param-struct1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_struct_param\nMode\.+: C\nType\.+: struct tag_struct_name
+Base name\.+: mystruct_param\nMode\.+: C\nType\.+: MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-param-type1/main.c b/regression/cbmc/typedef-param-type1/main.c
new file mode 100644
index 00000000000..b4c915066b6
--- /dev/null
+++ b/regression/cbmc/typedef-param-type1/main.c
@@ -0,0 +1,7 @@
+
+typedef int MYINT;
+
+void fun(int int_param, MYINT myint_param)
+{
+
+}
diff --git a/regression/cbmc/typedef-param-type1/test.desc b/regression/cbmc/typedef-param-type1/test.desc
new file mode 100644
index 00000000000..14659940cde
--- /dev/null
+++ b/regression/cbmc/typedef-param-type1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_param\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_param\nMode\.+: C\nType\.+: MYINT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-param-type2/main.c b/regression/cbmc/typedef-param-type2/main.c
new file mode 100644
index 00000000000..b5974fb6bbb
--- /dev/null
+++ b/regression/cbmc/typedef-param-type2/main.c
@@ -0,0 +1,8 @@
+
+typedef int MYINT;
+typedef int ALTINT;
+
+void fun(int int_param, MYINT myint_param, ALTINT altint_param)
+{
+
+}
diff --git a/regression/cbmc/typedef-param-type2/test.desc b/regression/cbmc/typedef-param-type2/test.desc
new file mode 100644
index 00000000000..14e7db9d3d4
--- /dev/null
+++ b/regression/cbmc/typedef-param-type2/test.desc
@@ -0,0 +1,12 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_param\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_param\nMode\.+: C\nType\.+: MYINT
+Base name\.+: altint_param\nMode\.+: C\nType\.+: ALTINT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-param-type3/main.c b/regression/cbmc/typedef-param-type3/main.c
new file mode 100644
index 00000000000..4d542e10c13
--- /dev/null
+++ b/regression/cbmc/typedef-param-type3/main.c
@@ -0,0 +1,7 @@
+
+typedef int MYINT;
+typedef MYINT CHAINEDINT;
+
+void fun(int int_param, MYINT myint_param, CHAINEDINT chainedint_param)
+{
+}
diff --git a/regression/cbmc/typedef-param-type3/test.desc b/regression/cbmc/typedef-param-type3/test.desc
new file mode 100644
index 00000000000..1f10dea2551
--- /dev/null
+++ b/regression/cbmc/typedef-param-type3/test.desc
@@ -0,0 +1,12 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_param\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_param\nMode\.+: C\nType\.+: MYINT
+Base name\.+: chainedint_param\nMode\.+: C\nType\.+: CHAINEDINT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-param-union1/main.c b/regression/cbmc/typedef-param-union1/main.c
new file mode 100644
index 00000000000..8f961614e5d
--- /dev/null
+++ b/regression/cbmc/typedef-param-union1/main.c
@@ -0,0 +1,10 @@
+
+typedef union tag_union_name
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun(union tag_union_name tag_union_param, MYUNION myunion_param)
+{
+}
diff --git a/regression/cbmc/typedef-param-union1/test.desc b/regression/cbmc/typedef-param-union1/test.desc
new file mode 100644
index 00000000000..37ab0aee08c
--- /dev/null
+++ b/regression/cbmc/typedef-param-union1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_union_param\nMode\.+: C\nType\.+: union tag_union_name
+Base name\.+: myunion_param\nMode\.+: C\nType\.+: MYUNION
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-return-anon-struct1/main.c b/regression/cbmc/typedef-return-anon-struct1/main.c
new file mode 100644
index 00000000000..0195b955cdd
--- /dev/null
+++ b/regression/cbmc/typedef-return-anon-struct1/main.c
@@ -0,0 +1,12 @@
+
+typedef struct
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+MYSTRUCT fun()
+{
+  MYSTRUCT return_variable = {.x = 1, .y = 3.14f};
+  return return_variable;
+}
diff --git a/regression/cbmc/typedef-return-anon-struct1/test.desc b/regression/cbmc/typedef-return-anon-struct1/test.desc
new file mode 100644
index 00000000000..420ac1295ac
--- /dev/null
+++ b/regression/cbmc/typedef-return-anon-struct1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: return\nMode\.+: C\nType\.+: MYSTRUCT
+Base name\.+: fun\nMode\.+: C\nType\.+: MYSTRUCT \(\)
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-return-anon-union1/main.c b/regression/cbmc/typedef-return-anon-union1/main.c
new file mode 100644
index 00000000000..3bc7d19d5b7
--- /dev/null
+++ b/regression/cbmc/typedef-return-anon-union1/main.c
@@ -0,0 +1,15 @@
+
+typedef union
+{
+  int x;
+  float y;
+} MYUNION;
+
+
+MYUNION fun()
+{
+  MYUNION return_variable = {1};
+  return return_variable;
+}
+
+
diff --git a/regression/cbmc/typedef-return-anon-union1/test.desc b/regression/cbmc/typedef-return-anon-union1/test.desc
new file mode 100644
index 00000000000..8d8d41a4dfe
--- /dev/null
+++ b/regression/cbmc/typedef-return-anon-union1/test.desc
@@ -0,0 +1,10 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: fun\nMode\.+: C\nType\.+: MYUNION \(\)
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-return-struct1/main.c b/regression/cbmc/typedef-return-struct1/main.c
new file mode 100644
index 00000000000..30c1323555c
--- /dev/null
+++ b/regression/cbmc/typedef-return-struct1/main.c
@@ -0,0 +1,20 @@
+
+typedef struct tag_struct_name
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+struct tag_struct_name fun()
+{
+  struct tag_struct_name return_variable = { .x = 1, .y = 3.14f};
+  return return_variable;
+}
+
+MYSTRUCT fun2()
+{
+  MYSTRUCT return_variable = { .x = 1, .y = 3.14f};
+  return return_variable;
+}
+
+
diff --git a/regression/cbmc/typedef-return-struct1/test.desc b/regression/cbmc/typedef-return-struct1/test.desc
new file mode 100644
index 00000000000..c4a9dc3550c
--- /dev/null
+++ b/regression/cbmc/typedef-return-struct1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: fun\nMode\.+: C\nType\.+: struct tag_struct_name \(\)
+Base name\.+: fun2\nMode\.+: C\nType\.+: MYSTRUCT \(\)
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-return-type1/main.c b/regression/cbmc/typedef-return-type1/main.c
new file mode 100644
index 00000000000..1ba7f426f89
--- /dev/null
+++ b/regression/cbmc/typedef-return-type1/main.c
@@ -0,0 +1,12 @@
+
+typedef int MYINT;
+
+int fun()
+{
+  return 4;
+}
+
+MYINT fun2()
+{
+  return 5;
+}
diff --git a/regression/cbmc/typedef-return-type1/test.desc b/regression/cbmc/typedef-return-type1/test.desc
new file mode 100644
index 00000000000..0ebbe5109a7
--- /dev/null
+++ b/regression/cbmc/typedef-return-type1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: fun\nMode\.+: C\nType\.+: signed int \(\)
+Base name\.+: fun2\nMode\.+: C\nType\.+: MYINT \(\)
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-return-type2/main.c b/regression/cbmc/typedef-return-type2/main.c
new file mode 100644
index 00000000000..0d94ab54da3
--- /dev/null
+++ b/regression/cbmc/typedef-return-type2/main.c
@@ -0,0 +1,13 @@
+
+typedef int MYINT;
+typedef int ALTINT;
+
+MYINT fun()
+{
+
+}
+
+ALTINT fun2()
+{
+
+}
diff --git a/regression/cbmc/typedef-return-type2/test.desc b/regression/cbmc/typedef-return-type2/test.desc
new file mode 100644
index 00000000000..27b2e77902d
--- /dev/null
+++ b/regression/cbmc/typedef-return-type2/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: fun\nMode\.+: C\nType\.+: MYINT \(\)
+Base name\.+: fun2\nMode\.+: C\nType\.+: ALTINT \(\)
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-return-type3/main.c b/regression/cbmc/typedef-return-type3/main.c
new file mode 100644
index 00000000000..e246757c692
--- /dev/null
+++ b/regression/cbmc/typedef-return-type3/main.c
@@ -0,0 +1,12 @@
+
+typedef int MYINT;
+typedef MYINT CHAINEDINT;
+
+MYINT fun()
+{
+}
+
+CHAINEDINT fun2()
+{
+
+}
\ No newline at end of file
diff --git a/regression/cbmc/typedef-return-type3/test.desc b/regression/cbmc/typedef-return-type3/test.desc
new file mode 100644
index 00000000000..7cfecafece9
--- /dev/null
+++ b/regression/cbmc/typedef-return-type3/test.desc
@@ -0,0 +1,10 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+Base name\.+: fun\nMode\.+: C\nType\.+: MYINT \(\)
+Base name\.+: fun2\nMode\.+: C\nType\.+: CHAINEDINT \(\)
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-return-union1/main.c b/regression/cbmc/typedef-return-union1/main.c
new file mode 100644
index 00000000000..ad69cb04545
--- /dev/null
+++ b/regression/cbmc/typedef-return-union1/main.c
@@ -0,0 +1,20 @@
+
+typedef union tag_union_name
+{
+  int x;
+  float y;
+} MYUNION;
+
+union tag_union_name fun()
+{
+  union tag_union_name return_variable = {1};
+  return return_variable;
+}
+
+MYUNION fun2()
+{
+  MYUNION return_variable = {1};
+  return return_variable;
+}
+
+
diff --git a/regression/cbmc/typedef-return-union1/test.desc b/regression/cbmc/typedef-return-union1/test.desc
new file mode 100644
index 00000000000..b1668066f08
--- /dev/null
+++ b/regression/cbmc/typedef-return-union1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: fun\nMode\.+: C\nType\.+: union tag_union_name \(\)
+Base name\.+: fun2\nMode\.+: C\nType\.+: MYUNION \(\)
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-struct1/main.c b/regression/cbmc/typedef-struct1/main.c
new file mode 100644
index 00000000000..dac5abf77b8
--- /dev/null
+++ b/regression/cbmc/typedef-struct1/main.c
@@ -0,0 +1,12 @@
+
+typedef struct tag_struct_name
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun()
+{
+  struct tag_struct_name tag_struct_var = {.x = 1, .y = 3.14f};
+  MYSTRUCT mystruct_var = {.x = 3, .y = 2.1f};
+}
diff --git a/regression/cbmc/typedef-struct1/test.desc b/regression/cbmc/typedef-struct1/test.desc
new file mode 100644
index 00000000000..90f1c22933a
--- /dev/null
+++ b/regression/cbmc/typedef-struct1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_struct_var\nMode\.+: C\nType\.+: struct tag_struct_name
+Base name\.+: mystruct_var\nMode\.+: C\nType\.+: MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-struct2/main.c b/regression/cbmc/typedef-struct2/main.c
new file mode 100644
index 00000000000..dac5abf77b8
--- /dev/null
+++ b/regression/cbmc/typedef-struct2/main.c
@@ -0,0 +1,12 @@
+
+typedef struct tag_struct_name
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun()
+{
+  struct tag_struct_name tag_struct_var = {.x = 1, .y = 3.14f};
+  MYSTRUCT mystruct_var = {.x = 3, .y = 2.1f};
+}
diff --git a/regression/cbmc/typedef-struct2/test.desc b/regression/cbmc/typedef-struct2/test.desc
new file mode 100644
index 00000000000..90f1c22933a
--- /dev/null
+++ b/regression/cbmc/typedef-struct2/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_struct_var\nMode\.+: C\nType\.+: struct tag_struct_name
+Base name\.+: mystruct_var\nMode\.+: C\nType\.+: MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-type1/main.c b/regression/cbmc/typedef-type1/main.c
new file mode 100644
index 00000000000..43f028c7772
--- /dev/null
+++ b/regression/cbmc/typedef-type1/main.c
@@ -0,0 +1,8 @@
+
+typedef int MYINT;
+
+void fun()
+{
+  int int_var = 3;
+  MYINT myint_var = 5;
+}
diff --git a/regression/cbmc/typedef-type1/test.desc b/regression/cbmc/typedef-type1/test.desc
new file mode 100644
index 00000000000..08d1f5abfcd
--- /dev/null
+++ b/regression/cbmc/typedef-type1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_var\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_var\nMode\.+: C\nType\.+: MYINT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-type2/main.c b/regression/cbmc/typedef-type2/main.c
new file mode 100644
index 00000000000..acb1cce2da4
--- /dev/null
+++ b/regression/cbmc/typedef-type2/main.c
@@ -0,0 +1,10 @@
+
+typedef int MYINT;
+typedef int ALTINT;
+
+void fun()
+{
+  int int_var = 3;
+  MYINT myint_var = 5;
+  ALTINT altint_var = 7;
+}
diff --git a/regression/cbmc/typedef-type2/test.desc b/regression/cbmc/typedef-type2/test.desc
new file mode 100644
index 00000000000..76d1d114a19
--- /dev/null
+++ b/regression/cbmc/typedef-type2/test.desc
@@ -0,0 +1,12 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_var\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_var\nMode\.+: C\nType\.+: MYINT
+Base name\.+: altint_var\nMode\.+: C\nType\.+: ALTINT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-type3/main.c b/regression/cbmc/typedef-type3/main.c
new file mode 100644
index 00000000000..5855e0c24cb
--- /dev/null
+++ b/regression/cbmc/typedef-type3/main.c
@@ -0,0 +1,10 @@
+
+typedef int MYINT;
+typedef MYINT CHAINEDINT;
+
+void fun()
+{
+  int int_var = 3;
+  MYINT myint_var = 5;
+  CHAINEDINT chainedint_var = 5;
+}
diff --git a/regression/cbmc/typedef-type3/test.desc b/regression/cbmc/typedef-type3/test.desc
new file mode 100644
index 00000000000..cc5ad52d953
--- /dev/null
+++ b/regression/cbmc/typedef-type3/test.desc
@@ -0,0 +1,12 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_var\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_var\nMode\.+: C\nType\.+: MYINT
+Base name\.+: chainedint_var\nMode\.+: C\nType\.+: CHAINEDINT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-type4/main.c b/regression/cbmc/typedef-type4/main.c
new file mode 100644
index 00000000000..aa2ec9ad7fb
--- /dev/null
+++ b/regression/cbmc/typedef-type4/main.c
@@ -0,0 +1,8 @@
+
+typedef int MYINT;
+
+void fun()
+{
+  int int_var = 3;
+  MYINT myint_var = 5, another_myint_var = 10;
+}
diff --git a/regression/cbmc/typedef-type4/test.desc b/regression/cbmc/typedef-type4/test.desc
new file mode 100644
index 00000000000..1c0c063b8e1
--- /dev/null
+++ b/regression/cbmc/typedef-type4/test.desc
@@ -0,0 +1,12 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_var\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_var\nMode\.+: C\nType\.+: MYINT
+Base name\.+: another_myint_var\nMode\.+: C\nType\.+: MYINT
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-union1/main.c b/regression/cbmc/typedef-union1/main.c
new file mode 100644
index 00000000000..6f56f3c731b
--- /dev/null
+++ b/regression/cbmc/typedef-union1/main.c
@@ -0,0 +1,12 @@
+
+typedef union tag_union_name
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun()
+{
+  union tag_union_name tag_union_var = {1};
+  MYUNION myunion_var = {.y = 2.1f};
+}
diff --git a/regression/cbmc/typedef-union1/test.desc b/regression/cbmc/typedef-union1/test.desc
new file mode 100644
index 00000000000..e7ce9b6b459
--- /dev/null
+++ b/regression/cbmc/typedef-union1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_union_var\nMode\.+: C\nType\.+: union tag_union_name
+Base name\.+: myunion_var\nMode\.+: C\nType\.+: MYUNION
+--
+warning: ignoring
diff --git a/regression/cbmc/typedef-union2/main.c b/regression/cbmc/typedef-union2/main.c
new file mode 100644
index 00000000000..9ca707cf767
--- /dev/null
+++ b/regression/cbmc/typedef-union2/main.c
@@ -0,0 +1,12 @@
+
+typedef union tag_union_name
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun()
+{
+  union tag_union_name tag_union_var = {1}, another_tag_union_var = {1};
+  MYUNION myunion_var = {.y = 2.1f}, another_myunion_var = {.y = 3.1f};
+}
diff --git a/regression/cbmc/typedef-union2/test.desc b/regression/cbmc/typedef-union2/test.desc
new file mode 100644
index 00000000000..33cbbff29af
--- /dev/null
+++ b/regression/cbmc/typedef-union2/test.desc
@@ -0,0 +1,13 @@
+CORE
+main.c
+--show-symbol-table --function fun
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_union_var\nMode\.+: C\nType\.+: union tag_union_name
+Base name\.+: another_tag_union_var\nMode\.+: C\nType\.+: union tag_union_name
+Base name\.+: myunion_var\nMode\.+: C\nType\.+: MYUNION
+Base name\.+: another_myunion_var\nMode\.+: C\nType\.+: MYUNION
+--
+warning: ignoring
diff --git a/regression/cpp-from-CVS/Makefile b/regression/cpp-from-CVS/Makefile
index b092e240b99..e28536a2988 100644
--- a/regression/cpp-from-CVS/Makefile
+++ b/regression/cpp-from-CVS/Makefile
@@ -12,3 +12,8 @@ show:
 			vim -o "$$dir/main.c" "$$dir/main.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/cpp-linter/Makefile b/regression/cpp-linter/Makefile
index b84f9ae3d18..097b463fce5 100644
--- a/regression/cpp-linter/Makefile
+++ b/regression/cpp-linter/Makefile
@@ -18,3 +18,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/cpp/Makefile b/regression/cpp/Makefile
index b03e120015b..87af55e3306 100644
--- a/regression/cpp/Makefile
+++ b/regression/cpp/Makefile
@@ -18,3 +18,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/fault-localization/Makefile b/regression/fault-localization/Makefile
index cbdd3378bac..9a14abc905f 100644
--- a/regression/fault-localization/Makefile
+++ b/regression/fault-localization/Makefile
@@ -18,3 +18,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/goto-analyzer/Makefile b/regression/goto-analyzer/Makefile
index 2630bf17097..ca7e7707afe 100644
--- a/regression/goto-analyzer/Makefile
+++ b/regression/goto-analyzer/Makefile
@@ -18,3 +18,8 @@ show:
 			vim -o "$$dir/*.java" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/goto-analyzer/approx-array-variable-const-fp/main.c b/regression/goto-analyzer/approx-array-variable-const-fp/main.c
new file mode 100644
index 00000000000..7896e3402c0
--- /dev/null
+++ b/regression/goto-analyzer/approx-array-variable-const-fp/main.c
@@ -0,0 +1,34 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+const void_fp fp_tbl[] = {f2, f3 ,f4};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  fp_tbl[i]();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/approx-array-variable-const-fp/test.desc b/regression/goto-analyzer/approx-array-variable-const-fp/test.desc
new file mode 100644
index 00000000000..83a930d1c36
--- /dev/null
+++ b/regression/goto-analyzer/approx-array-variable-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f2 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f3 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f4 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^\s*IF fp_tbl\[\(signed long int\)i\] == f1 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f5 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f6 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f7 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f8 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f9 THEN GOTO [0-9]$
+^warning: ignoring
diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-cast-const-fp/main.c b/regression/goto-analyzer/approx-const-fp-array-variable-cast-const-fp/main.c
new file mode 100644
index 00000000000..8fda2e71af4
--- /dev/null
+++ b/regression/goto-analyzer/approx-const-fp-array-variable-cast-const-fp/main.c
@@ -0,0 +1,41 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void(* const fp_tbl[3])(void) =
+{
+  (void(*)())f2,
+  (void(*)())f3,
+  (void(*)())f4,
+};
+
+
+void func(int i)
+{
+  const void_fp fp = fp_tbl[i];
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-cast-const-fp/test.desc b/regression/goto-analyzer/approx-const-fp-array-variable-cast-const-fp/test.desc
new file mode 100644
index 00000000000..a937e306d31
--- /dev/null
+++ b/regression/goto-analyzer/approx-const-fp-array-variable-cast-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
+^\s*IF fp_tbl\[\(signed long int\)i\] == f1 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f5 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f6 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f7 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f8 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f9 THEN GOTO [0-9]$
diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-const-fp-with-null/main.c b/regression/goto-analyzer/approx-const-fp-array-variable-const-fp-with-null/main.c
new file mode 100644
index 00000000000..72a600aa80c
--- /dev/null
+++ b/regression/goto-analyzer/approx-const-fp-array-variable-const-fp-with-null/main.c
@@ -0,0 +1,35 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+const void_fp fp_tbl[] = {f2, f3 ,f4, 0};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  const void_fp fp = fp_tbl[i];
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-const-fp-with-null/test.desc b/regression/goto-analyzer/approx-const-fp-array-variable-const-fp-with-null/test.desc
new file mode 100644
index 00000000000..a937e306d31
--- /dev/null
+++ b/regression/goto-analyzer/approx-const-fp-array-variable-const-fp-with-null/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
+^\s*IF fp_tbl\[\(signed long int\)i\] == f1 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f5 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f6 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f7 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f8 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f9 THEN GOTO [0-9]$
diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-const-fp/main.c b/regression/goto-analyzer/approx-const-fp-array-variable-const-fp/main.c
new file mode 100644
index 00000000000..7eea22141bd
--- /dev/null
+++ b/regression/goto-analyzer/approx-const-fp-array-variable-const-fp/main.c
@@ -0,0 +1,35 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+const void_fp fp_tbl[] = {f2, f3 ,f4};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  const void_fp fp = fp_tbl[i];
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-const-fp/test.desc b/regression/goto-analyzer/approx-const-fp-array-variable-const-fp/test.desc
new file mode 100644
index 00000000000..a937e306d31
--- /dev/null
+++ b/regression/goto-analyzer/approx-const-fp-array-variable-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
+^\s*IF fp_tbl\[\(signed long int\)i\] == f1 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f5 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f6 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f7 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f8 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f9 THEN GOTO [0-9]$
diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-const-pointer-const-struct-non-const-fp/main.c b/regression/goto-analyzer/approx-const-fp-array-variable-const-pointer-const-struct-non-const-fp/main.c
new file mode 100644
index 00000000000..67d256f0c7b
--- /dev/null
+++ b/regression/goto-analyzer/approx-const-fp-array-variable-const-pointer-const-struct-non-const-fp/main.c
@@ -0,0 +1,50 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+struct action
+{
+  void_fp fun;
+};
+
+const struct action rec = { .fun = f2 };
+const struct action rec2 = { .fun = f3 };
+const struct action rec3 = { .fun = f4 };
+
+const struct action * const action_list[4] =
+{
+  &rec,
+  &rec2,
+  &rec3,
+  &rec
+};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  const void_fp fp = action_list[i]->fun;
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/approx-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc
new file mode 100644
index 00000000000..a937e306d31
--- /dev/null
+++ b/regression/goto-analyzer/approx-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
+^\s*IF fp_tbl\[\(signed long int\)i\] == f1 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f5 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f6 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f7 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f8 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f9 THEN GOTO [0-9]$
diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-const-struct-non-const-fp/main.c b/regression/goto-analyzer/approx-const-fp-array-variable-const-struct-non-const-fp/main.c
new file mode 100644
index 00000000000..e058e5f3c4f
--- /dev/null
+++ b/regression/goto-analyzer/approx-const-fp-array-variable-const-struct-non-const-fp/main.c
@@ -0,0 +1,51 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+struct stable
+{
+  int x;
+  void (*fp)(void);
+};
+
+const struct stable stable_table [3] =
+{
+  { 1, f2 },
+  { 2, f3 },
+  { 3, f4 }
+};
+
+const struct stable another_table = { 4, f5 };
+
+
+void func(int i)
+{
+  const void_fp fp = stable_table[i].fp;
+
+  // Illegal
+  // stable_table[1] = another_table;
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+  return 0;
+}
diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/approx-const-fp-array-variable-const-struct-non-const-fp/test.desc
new file mode 100644
index 00000000000..a937e306d31
--- /dev/null
+++ b/regression/goto-analyzer/approx-const-fp-array-variable-const-struct-non-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
+^\s*IF fp_tbl\[\(signed long int\)i\] == f1 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f5 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f6 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f7 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f8 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f9 THEN GOTO [0-9]$
diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-invalid-cast-const-fp/main.c b/regression/goto-analyzer/approx-const-fp-array-variable-invalid-cast-const-fp/main.c
new file mode 100644
index 00000000000..ca882ffd6b3
--- /dev/null
+++ b/regression/goto-analyzer/approx-const-fp-array-variable-invalid-cast-const-fp/main.c
@@ -0,0 +1,77 @@
+#include 
+
+int f1 (void)
+{
+  printf("%i\n", 1);
+  return 1;
+}
+int f2 (void)
+{
+  printf("%i\n", 2);
+  return 2;
+}
+int f3 (void)
+{
+  printf("%i\n", 3);
+  return 3;
+}
+int f4 (void)
+{
+  printf("%i\n", 4);
+  return 4;
+}
+int f5 (void)
+{
+  printf("%i\n", 5);
+  return 5;
+}
+int f6 (void)
+{
+  printf("%i\n", 6);
+  return 6;
+}
+int f7 (void)
+{
+  printf("%i\n", 7);
+  return 7;
+}
+int f8 (void)
+{
+  printf("%i\n", 8);
+  return 8;
+}
+int f9 (void)
+{
+  printf("%i\n", 9);
+  return 9;
+}
+
+typedef void(*void_fp)(void);
+typedef int(*int_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const int_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void(* const fp_tbl[3])(void) =
+{
+  (void(*)())f2,
+  (void(*)())f3,
+  (void(*)())f4,
+};
+
+
+void func(int i)
+{
+  const void_fp fp = fp_tbl[i];
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+  return 0;
+}
diff --git a/regression/goto-analyzer/approx-const-fp-array-variable-invalid-cast-const-fp/test.desc b/regression/goto-analyzer/approx-const-fp-array-variable-invalid-cast-const-fp/test.desc
new file mode 100644
index 00000000000..6df2697851a
--- /dev/null
+++ b/regression/goto-analyzer/approx-const-fp-array-variable-invalid-cast-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == \(const void_fp\)f2 THEN GOTO [0-9]$
+^\s*IF fp == \(const void_fp\)f3 THEN GOTO [0-9]$
+^\s*IF fp == \(const void_fp\)f4 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
+^\s*IF fp_tbl\[\(signed long int\)i\] == f1 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f5 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f6 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f7 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f8 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f9 THEN GOTO [0-9]$
diff --git a/regression/goto-analyzer/constant_propagation_01/constant_propagation1.c b/regression/goto-analyzer/constant_propagation_01/constant_propagation1.c
new file mode 100644
index 00000000000..801a21535a9
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_01/constant_propagation1.c
@@ -0,0 +1,14 @@
+#include 
+
+int main()
+{
+  int i, j=20;
+  
+  if (j==20)
+  {
+    int x=1,y=2,z;
+    z=x+y;
+    assert(z==3);
+  }
+    
+}
diff --git a/regression/goto-analyzer/constant_propagation_01/test.desc b/regression/goto-analyzer/constant_propagation_01/test.desc
new file mode 100644
index 00000000000..1eb849c3c7a
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_01/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+constant_propagation1.c
+--constants --simplify out.goto
+^EXIT=0$
+^SIGNAL=0$
+^SIMPLIFIED:  assert: 1, assume: 0, goto: 2, assigns: 5, function calls: 0$
+^UNMODIFIED:  assert: 0, assume: 0, goto: 0, assigns: 12, function calls: 2$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_02/constant_propagation_02.c b/regression/goto-analyzer/constant_propagation_02/constant_propagation_02.c
new file mode 100644
index 00000000000..ff139437bd8
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_02/constant_propagation_02.c
@@ -0,0 +1,13 @@
+#include 
+
+int main()
+{
+  int i=0, j=2;
+
+  if (i==0) 
+  {
+    i++;
+    j++;
+  }
+  assert(j!=3);
+}
diff --git a/regression/goto-analyzer/constant_propagation_02/original b/regression/goto-analyzer/constant_propagation_02/original
new file mode 100644
index 00000000000..13a9e245c81
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_02/original
@@ -0,0 +1,3 @@
+Task defaults to --show
+Domain defaults to --constants
+GOTO-ANALYSER version 5.5 64-bit x86_64 linux
diff --git a/regression/goto-analyzer/constant_propagation_02/simplified b/regression/goto-analyzer/constant_propagation_02/simplified
new file mode 100644
index 00000000000..6c722a607de
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_02/simplified
@@ -0,0 +1,81 @@
+Reading GOTO program from `out.goto'
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+main /* main */
+        // 0 file constant_propagation_02.c line 5 function main
+        signed int i;
+        // 1 file constant_propagation_02.c line 5 function main
+        i = 0;
+        // 2 file constant_propagation_02.c line 5 function main
+        signed int j;
+        // 3 file constant_propagation_02.c line 5 function main
+        j = 2;
+        // 4 file constant_propagation_02.c line 7 function main
+        IF FALSE THEN GOTO 1
+        // 5 file constant_propagation_02.c line 9 function main
+        0 = 1;
+        // 6 file constant_propagation_02.c line 10 function main
+        2 = 3;
+        // 7 no location
+     1: SKIP
+        // 8 file constant_propagation_02.c line 12 function main
+        ASSERT FALSE // assertion j!=3
+        // 9 file constant_propagation_02.c line 12 function main
+        GOTO 2
+        // 10 file constant_propagation_02.c line 12 function main
+        (void)0;
+        // 11 no location
+     2: SKIP
+        // 12 file constant_propagation_02.c line 13 function main
+        dead j;
+        // 13 file constant_propagation_02.c line 13 function main
+        dead i;
+        // 14 file constant_propagation_02.c line 13 function main
+        main#return_value = NONDET(signed int);
+        // 15 file constant_propagation_02.c line 13 function main
+        END_FUNCTION
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+_start /* _start */
+        // 16 no location
+        __CPROVER_initialize();
+        // 17 file constant_propagation_02.c line 3
+        main();
+        // 18 file constant_propagation_02.c line 3
+        return' = main#return_value;
+        // 19 file constant_propagation_02.c line 3
+        dead main#return_value;
+        // 20 file constant_propagation_02.c line 3
+        OUTPUT("return", return');
+        // 21 no location
+        END_FUNCTION
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+__CPROVER_initialize /* __CPROVER_initialize */
+        // 22 no location
+        // Labels: __CPROVER_HIDE
+        SKIP
+        // 23 file  line 39
+        __CPROVER_dead_object = NULL;
+        // 24 file  line 38
+        __CPROVER_deallocated = NULL;
+        // 25 file  line 42
+        __CPROVER_malloc_is_new_array = FALSE;
+        // 26 file  line 40
+        __CPROVER_malloc_object = NULL;
+        // 27 file  line 41
+        __CPROVER_malloc_size = 0ul;
+        // 28 file  line 43
+        __CPROVER_memory_leak = NULL;
+        // 29 file  line 31
+        __CPROVER_next_thread_id = 0ul;
+        // 30 file  line 85
+        __CPROVER_pipe_count = 0u;
+        // 31 file  line 65
+        __CPROVER_rounding_mode = 0;
+        // 32 file  line 29
+        __CPROVER_thread_id = 0ul;
+        // 33 file  line 30
+        __CPROVER_threads_exited = ARRAY_OF(FALSE);
+        // 34 no location
+        END_FUNCTION
diff --git a/regression/goto-analyzer/constant_propagation_02/test.desc b/regression/goto-analyzer/constant_propagation_02/test.desc
new file mode 100644
index 00000000000..20cc5fcf86e
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_02/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+constant_propagation_02.c
+--constants --simplify out.goto
+^EXIT=0$
+^SIGNAL=0$
+^SIMPLIFIED:  assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$
+^UNMODIFIED:  assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_03/constant_propagation_03.c b/regression/goto-analyzer/constant_propagation_03/constant_propagation_03.c
new file mode 100644
index 00000000000..f08f6020d82
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_03/constant_propagation_03.c
@@ -0,0 +1,13 @@
+#include 
+
+int main()
+{
+  int i=0, j=2;
+
+  if (i==0) 
+  {
+    i++;
+    j++;
+  }
+  assert(j==3);
+}
diff --git a/regression/goto-analyzer/constant_propagation_03/test.desc b/regression/goto-analyzer/constant_propagation_03/test.desc
new file mode 100644
index 00000000000..2225c1a666e
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_03/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+constant_propagation_03.c
+--constants --simplify out.goto
+^EXIT=0$
+^SIGNAL=0$
+^SIMPLIFIED:  assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$
+^UNMODIFIED:  assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_04/constant_propagation_04.c b/regression/goto-analyzer/constant_propagation_04/constant_propagation_04.c
new file mode 100644
index 00000000000..ca003ccd2b8
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_04/constant_propagation_04.c
@@ -0,0 +1,13 @@
+#include 
+
+int main()
+{
+  int i=0, j=2;
+
+  if (i<50) 
+  {
+    i++;
+    j++;
+  }
+  assert(j==3);
+}
diff --git a/regression/goto-analyzer/constant_propagation_04/test.desc b/regression/goto-analyzer/constant_propagation_04/test.desc
new file mode 100644
index 00000000000..2510b3f8a5e
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_04/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+constant_propagation_04.c
+--constants --simplify out.goto
+^EXIT=0$
+^SIGNAL=0$
+^SIMPLIFIED:  assert: 1, assume: 0, goto: 2, assigns: 6, function calls: 0$
+^UNMODIFIED:  assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_05/constant_propagation_05.c b/regression/goto-analyzer/constant_propagation_05/constant_propagation_05.c
new file mode 100644
index 00000000000..037fbbe0632
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_05/constant_propagation_05.c
@@ -0,0 +1,13 @@
+#include 
+
+int main()
+{
+  int i=0, j=2;
+
+  if (i<50) 
+  {
+    i++;
+    j++;
+  }
+  assert(j!=3);
+}
diff --git a/regression/goto-analyzer/constant_propagation_05/test.desc b/regression/goto-analyzer/constant_propagation_05/test.desc
new file mode 100644
index 00000000000..ddb22cc3616
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_05/test.desc
@@ -0,0 +1,8 @@
+FUTURE
+constant_propagation_05.c
+--constants --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] file constant_propagation_05.c line 12 function main, assertion j!=3: FAILURE (if reachable)$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_06/constant_propagation_06.c b/regression/goto-analyzer/constant_propagation_06/constant_propagation_06.c
new file mode 100644
index 00000000000..d1d29427250
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_06/constant_propagation_06.c
@@ -0,0 +1,30 @@
+#include 
+
+int main()
+{
+  int i, j=20;
+
+  if(i>=20)
+    assert(i>=10); // success
+
+  if(i>=10 && i<=20)
+    assert(i!=30); // success
+
+  if(i>=10 && i<=20)
+    assert(i!=15); // fails
+
+  if(i<1 && i>10)
+    assert(0); // success
+
+  if(i>=10 && j>=i)
+    assert(j>=10); // success
+
+  if(i>=j)
+    assert(i>=j); // unknown
+
+  if(i>10)
+    assert(i>=11); // success
+
+  if(i<=100 && j=10: SUCCESS$
+^\[main.assertion.2\] file constant_propagation_06.c line 11 function main, assertion i!=30: SUCCESS$
+^\[main.assertion.3\] file constant_propagation_06.c line 14 function main, assertion i!=15: UNKNOWN$
+^\[main.assertion.4\] file constant_propagation_06.c line 17 function main, assertion 0: SUCCESS$
+^\[main.assertion.5\] file constant_propagation_06.c line 20 function main, assertion j>=10: SUCCESS$
+^\[main.assertion.6\] file constant_propagation_06.c line 23 function main, assertion i>=j: UNKNOWN$
+^\[main.assertion.7\] file constant_propagation_06.c line 26 function main, assertion i>=11: SUCCESS$
+^\[main.assertion.8\] file constant_propagation_06.c line 29 function main, assertion j<100: SUCCESS$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_07/constant_propagation_07.c b/regression/goto-analyzer/constant_propagation_07/constant_propagation_07.c
new file mode 100644
index 00000000000..40b04edfdd0
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_07/constant_propagation_07.c
@@ -0,0 +1,14 @@
+#include 
+
+int main()
+{
+  int i=0, j=2;
+
+  while (i<50) 
+  {
+    i++;
+    j++;
+  }
+  assert(i<51);
+}
+
diff --git a/regression/goto-analyzer/constant_propagation_07/test.desc b/regression/goto-analyzer/constant_propagation_07/test.desc
new file mode 100644
index 00000000000..615893d4f78
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_07/test.desc
@@ -0,0 +1,8 @@
+FUTURE
+constant_propagation_07.c
+--constants --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] file constant_propagation_07.c line 12 function main, assertion i<51: UNKNOWN$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_08/constant_propagation_08.c b/regression/goto-analyzer/constant_propagation_08/constant_propagation_08.c
new file mode 100644
index 00000000000..3909e3889e4
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_08/constant_propagation_08.c
@@ -0,0 +1,16 @@
+#include 
+
+int main()
+{
+  int i=0, j=2;
+
+  while (i<=50) 
+  {
+    i++;
+    j++;
+  }
+  assert(i<50);
+  assert(i<51);
+  assert(i<52);
+}
+
diff --git a/regression/goto-analyzer/constant_propagation_08/test.desc b/regression/goto-analyzer/constant_propagation_08/test.desc
new file mode 100644
index 00000000000..994c2c532df
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_08/test.desc
@@ -0,0 +1,10 @@
+FUTURE
+constant_propagation_08.c
+--intervals --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] file constant_propagation_08.c line 12 function main, assertion i<50: UNKNOWN$
+^\[main.assertion.2\] file constant_propagation_08.c line 13 function main, assertion i<51: UNKNOWN$
+^\[main.assertion.3\] file constant_propagation_08.c line 14 function main, assertion i<52: SUCCESS$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_09/constant_propagation_09.c b/regression/goto-analyzer/constant_propagation_09/constant_propagation_09.c
new file mode 100644
index 00000000000..002e9063228
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_09/constant_propagation_09.c
@@ -0,0 +1,14 @@
+#include 
+
+int main()
+{
+  int i=0, j=2;
+
+  while (i<=50) 
+  {
+    i++;
+    j++;
+  }
+  assert(j<52);
+}
+
diff --git a/regression/goto-analyzer/constant_propagation_09/test.desc b/regression/goto-analyzer/constant_propagation_09/test.desc
new file mode 100644
index 00000000000..6a1b75f0c1b
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_09/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+constant_propagation_09.c
+--intervals --verify
+^EXIT=0$
+^SIGNAL=0$
+******** Function main
+^\[main.assertion.1\] file constant_propagation_09.c line 12 function main, assertion j<52: UNKNOWN$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_10/constant_propagation_10.c b/regression/goto-analyzer/constant_propagation_10/constant_propagation_10.c
new file mode 100644
index 00000000000..169f7965b9d
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_10/constant_propagation_10.c
@@ -0,0 +1,25 @@
+#include 
+int main()
+{
+  signed int i;
+  signed int j;
+  i = 0;
+   if(!(i >= 2))
+  {
+    j = j + 1;
+    i = i + 1;
+    if(!(i >= 2))
+    {
+      j = j + 1;
+      i = i + 1;
+      if(!(i >= 2))
+      {
+        j = j + 1;
+        i = i + 1;
+      }
+      assert(!(i < 2));
+    }
+  }
+  return 0;
+}
+
diff --git a/regression/goto-analyzer/constant_propagation_10/test.desc b/regression/goto-analyzer/constant_propagation_10/test.desc
new file mode 100644
index 00000000000..52d98cb611b
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_10/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+constant_propagation_10.c
+--constants --simplify out.goto
+^EXIT=0$
+^SIGNAL=0$
+^SIMPLIFIED:  assert: 1, assume: 0, goto: 4, assigns: 10, function calls: 0$
+^UNMODIFIED:  assert: 0, assume: 0, goto: 1, assigns: 10, function calls: 2$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_11/constant_propagation_11.c b/regression/goto-analyzer/constant_propagation_11/constant_propagation_11.c
new file mode 100644
index 00000000000..3022a4f0f19
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_11/constant_propagation_11.c
@@ -0,0 +1,17 @@
+#include 
+int main()
+{
+  int a[2];
+  int i;
+  i = 0;
+
+  if (i==0)
+    a[0]=1;
+  else
+    a[1]=2;
+
+  assert(a[0]==1 || a[1]==2);
+
+  return 0;
+}
+
diff --git a/regression/goto-analyzer/constant_propagation_11/test.desc b/regression/goto-analyzer/constant_propagation_11/test.desc
new file mode 100644
index 00000000000..7c849326cf6
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_11/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+constant_propagation_11.c
+--constants --simplify out.goto
+^EXIT=0$
+^SIGNAL=0$
+^SIMPLIFIED:  assert: 1, assume: 0, goto: 2, assigns: 5, function calls: 0$
+^UNMODIFIED:  assert: 0, assume: 0, goto: 4, assigns: 13, function calls: 2$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_12/constant_propagation_12.c b/regression/goto-analyzer/constant_propagation_12/constant_propagation_12.c
new file mode 100644
index 00000000000..55ea9ac7fc2
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_12/constant_propagation_12.c
@@ -0,0 +1,13 @@
+#include 
+int main()
+{
+  int a[2]={0,0};
+
+  if (a[0]==0)
+    a[0]=1;
+
+  assert(a[0]==0);
+
+  return 0;
+}
+
diff --git a/regression/goto-analyzer/constant_propagation_12/test.desc b/regression/goto-analyzer/constant_propagation_12/test.desc
new file mode 100644
index 00000000000..ca5803363ad
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_12/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+constant_propagation_12.c
+--constants --simplify out.goto
+^EXIT=0$
+^SIGNAL=0$
+^SIMPLIFIED:  assert: 1, assume: 0, goto: 3, assigns: 4, function calls: 0$
+^UNMODIFIED:  assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_13/constant_propagation_13.c b/regression/goto-analyzer/constant_propagation_13/constant_propagation_13.c
new file mode 100644
index 00000000000..ac5933e9177
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_13/constant_propagation_13.c
@@ -0,0 +1,14 @@
+#include 
+int main()
+{
+  int a[2]={0,0};
+  int i, y;
+
+  if (a[0]==0)
+    a[0]=1;
+
+  assert(a[0]==2);
+
+  return 0;
+}
+
diff --git a/regression/goto-analyzer/constant_propagation_13/test.desc b/regression/goto-analyzer/constant_propagation_13/test.desc
new file mode 100644
index 00000000000..22f10d125e3
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_13/test.desc
@@ -0,0 +1,8 @@
+FUTURE
+constant_propagation_13.c
+--constants --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] file constant_propagation_13.c line 10 function main, assertion a\[0\]==2: FAILURE$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_14/constant_propagation_14.c b/regression/goto-analyzer/constant_propagation_14/constant_propagation_14.c
new file mode 100644
index 00000000000..124d1e30a20
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_14/constant_propagation_14.c
@@ -0,0 +1,13 @@
+#include 
+int main()
+{
+  int a[2]={0,0};
+
+  if (a[0]==0)
+    a[0]=1;
+
+  assert(a[0]==1 /*|| a[0]==2*/);
+
+  return 0;
+}
+
diff --git a/regression/goto-analyzer/constant_propagation_14/test.desc b/regression/goto-analyzer/constant_propagation_14/test.desc
new file mode 100644
index 00000000000..a39a1f66cda
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_14/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+constant_propagation_14.c
+--constants --simplify out.goto
+^EXIT=0$
+^SIGNAL=0$
+^SIMPLIFIED:  assert: 1, assume: 0, goto: 0$
+^UNKNOWN:     assert: 0, assume: 0, goto: 0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_15/constant_propagation_15.c b/regression/goto-analyzer/constant_propagation_15/constant_propagation_15.c
new file mode 100644
index 00000000000..9a7e7692d62
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_15/constant_propagation_15.c
@@ -0,0 +1,13 @@
+#include 
+int main()
+{
+  int i=0, y;
+
+  if (i==0)
+    y=1;
+
+  assert(y==1);
+
+  return 0;
+}
+
diff --git a/regression/goto-analyzer/constant_propagation_15/test.desc b/regression/goto-analyzer/constant_propagation_15/test.desc
new file mode 100644
index 00000000000..20d36183eb0
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_15/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+constant_propagation_15.c
+--constants --simplify out.goto
+^EXIT=0$
+^SIGNAL=0$
+^SIMPLIFIED:  assert: 1, assume: 0, goto: 1, assigns: 4, function calls: 0$
+^UNMODIFIED:  assert: 0, assume: 0, goto: 2, assigns: 11, function calls: 2$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_16/constant_propagation_16.c b/regression/goto-analyzer/constant_propagation_16/constant_propagation_16.c
new file mode 100644
index 00000000000..102cfd7f812
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_16/constant_propagation_16.c
@@ -0,0 +1,13 @@
+#include 
+int main()
+{
+  int i=0, y;
+
+  if (i==0)
+    y=1;
+
+  assert(y==0);
+
+  return 0;
+}
+
diff --git a/regression/goto-analyzer/constant_propagation_16/test.desc b/regression/goto-analyzer/constant_propagation_16/test.desc
new file mode 100644
index 00000000000..b56c871deb4
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_16/test.desc
@@ -0,0 +1,8 @@
+FUTURE
+constant_propagation_16.c
+--constants --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] file constant_propagation_16.c line 9 function main, assertion y==0: FAILURE (if reachable)$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_17/constant_propagation_17.c b/regression/goto-analyzer/constant_propagation_17/constant_propagation_17.c
new file mode 100644
index 00000000000..8b426fe84b5
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_17/constant_propagation_17.c
@@ -0,0 +1,16 @@
+#include 
+int main()
+{
+  int a[2]={0,0};
+
+  if (a[0]==0)
+    a[0]=1;
+  else 
+    a[0]=2;
+
+  assert(a[0]==1 || a[0]==2);
+  assert(a[0]==1 && a[0]==2);
+
+  return 0;
+}
+
diff --git a/regression/goto-analyzer/constant_propagation_17/test.desc b/regression/goto-analyzer/constant_propagation_17/test.desc
new file mode 100644
index 00000000000..acecb91eb0a
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_17/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+constant_propagation_17.c
+--constants --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] file constant_propagation_17.c line 11 function main, assertion a\[0\]==1 || a\[0\]==2: SUCCESS$
+^\[main.assertion.2\] file constant_propagation_17.c line 12 function main, assertion a\[0\]==1 && a\[0\]==2: FAILURE$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/constant_propagation_18/constant_propagation_18.c b/regression/goto-analyzer/constant_propagation_18/constant_propagation_18.c
new file mode 100644
index 00000000000..6639f9b5c81
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_18/constant_propagation_18.c
@@ -0,0 +1,13 @@
+#include 
+int main()
+{
+  int a[2]={0,0};
+
+  if (a[0]==0)
+    a[0]=1;
+
+  assert(a[0]==2);
+
+  return 0;
+}
+
diff --git a/regression/goto-analyzer/constant_propagation_18/test.desc b/regression/goto-analyzer/constant_propagation_18/test.desc
new file mode 100644
index 00000000000..7ea74c4d264
--- /dev/null
+++ b/regression/goto-analyzer/constant_propagation_18/test.desc
@@ -0,0 +1,8 @@
+FUTURE
+constant_propagation_18.c
+--constants --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] file constant_propagation_18.c line 9 function main, assertion a\[0\]==2: FAILURE$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/intervals1/intervals1.c b/regression/goto-analyzer/intervals1/intervals1.c
index a797452b198..cdec490fe6d 100644
--- a/regression/goto-analyzer/intervals1/intervals1.c
+++ b/regression/goto-analyzer/intervals1/intervals1.c
@@ -2,8 +2,8 @@
 
 int main()
 {
-  int i, j;
-
+  int i, j=20;
+  
   if(i>=20)
     assert(i>=10);
 
diff --git a/regression/goto-analyzer/intervals1/test.desc b/regression/goto-analyzer/intervals1/test.desc
index 3e81f14023a..5a9802eeb20 100644
--- a/regression/goto-analyzer/intervals1/test.desc
+++ b/regression/goto-analyzer/intervals1/test.desc
@@ -1,6 +1,6 @@
-CORE
+KNOWNBUG
 intervals1.c
---intervals
+--intervals --verify
 ^EXIT=0$
 ^SIGNAL=0$
 ^\[main.assertion.1\] file intervals1.c line 8 function main, assertion i>=10: SUCCESS$
diff --git a/regression/goto-analyzer/intervals10/intervals10.c b/regression/goto-analyzer/intervals10/intervals10.c
new file mode 100644
index 00000000000..b27cc6f2001
--- /dev/null
+++ b/regression/goto-analyzer/intervals10/intervals10.c
@@ -0,0 +1,21 @@
+#include 
+
+int main()
+{
+  int i, j;
+
+  if(i<=100 && j100); // fails 
+
+  if(i<=100 && j100: FAILURE (if reachable)$
+^\[main.assertion.4\] file intervals10.c line 17 function main, assertion j<99: UNKNOWN$
+^\[main.assertion.5\] file intervals10.c line 20 function main, assertion j==100: FAILURE (if reachable)$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/intervals11/intervals11.c b/regression/goto-analyzer/intervals11/intervals11.c
new file mode 100644
index 00000000000..2f061cd554d
--- /dev/null
+++ b/regression/goto-analyzer/intervals11/intervals11.c
@@ -0,0 +1,43 @@
+#include 
+const int xLen = 10;
+const int Alen = 2;
+const int Blen = 1;
+float nondet_float();
+int main() {
+  float A[] = {1.0f,-0.5f};
+  float B[] = {1.0f};
+  int i,j;
+  float x[xLen];
+  float x_aux[xLen];
+  float y[xLen];
+  float y_aux[xLen];
+  float total=0;
+  for (i=0;i=-1 && x[i]<=1);
+    x_aux[i]=0;
+    y_aux[i]=0;
+  }
+  for(i=0;i=1;j--)
+      x_aux[j] = x_aux[j-1];
+    x_aux[0] = x[i];
+    /* Num, x values */
+    for (j = 0; j < Blen; j++) {
+      y[i] = y[i] + B[j]*x_aux[j];
+      assert(y[i]>=-1.0f && y[i]<=1.0f); //success
+    }
+    /* Den, y values */
+    for(j=0;j=-1.0f && y[i]<=1.0f); //fails
+    }
+    /* Update past y values */
+    for(j=Alen-2;j>=1;j--)
+      y_aux[j] = y_aux[j-1];
+    y_aux[0] = y[i];
+  }
+}
+
diff --git a/regression/goto-analyzer/intervals11/test.desc b/regression/goto-analyzer/intervals11/test.desc
new file mode 100644
index 00000000000..039cbffbeb0
--- /dev/null
+++ b/regression/goto-analyzer/intervals11/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+intervals11.c
+--intervals --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] file intervals11.c line 30 function main, assertion y\[i\]>=-1.0f && y\[i\]<=1.0f: UNKNOWN$
+^\[main.assertion.2\] file intervals11.c line 35 function main, assertion y\[i\]>=-1.0f && y\[i\]<=1.0f: UNKNOWN$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/intervals12/intervals12.c b/regression/goto-analyzer/intervals12/intervals12.c
new file mode 100644
index 00000000000..15d865adf80
--- /dev/null
+++ b/regression/goto-analyzer/intervals12/intervals12.c
@@ -0,0 +1,16 @@
+#include 
+
+int main (void) {
+  int i;
+  int j;
+
+  if (i <= 0 && j < i)
+    assert(j < 0);
+
+  if (j < i && i <= 0)
+    assert(j < 0);
+
+  return 0;
+}
+
+
diff --git a/regression/goto-analyzer/intervals12/test.desc b/regression/goto-analyzer/intervals12/test.desc
new file mode 100644
index 00000000000..59a724c28b5
--- /dev/null
+++ b/regression/goto-analyzer/intervals12/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+intervals12.c
+--intervals --verify
+^EXIT=0$
+^SIGNAL=0$
+^[main.assertion.1] file intervals12.c line 8 function main, assertion j < 0: SUCCESS$
+^[main.assertion.2] file intervals12.c line 11 function main, assertion j < 0: SUCCESS$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/intervals2/intervals2.c b/regression/goto-analyzer/intervals2/intervals2.c
index d1eaf25240e..d542854bb6a 100644
--- a/regression/goto-analyzer/intervals2/intervals2.c
+++ b/regression/goto-analyzer/intervals2/intervals2.c
@@ -2,10 +2,10 @@
 
 int main(){
   int x;
-  if (x > 0) {
-    if (x < 20) {
+  if (x > 0 && x < 20) {
+    //if (x < 20) {
       assert(x > -10 && x < 100);
-    }
+    //}
   }
   return 0;
 }
diff --git a/regression/goto-analyzer/intervals2/test.desc b/regression/goto-analyzer/intervals2/test.desc
index 16a8ca559e2..65aae030db1 100644
--- a/regression/goto-analyzer/intervals2/test.desc
+++ b/regression/goto-analyzer/intervals2/test.desc
@@ -1,6 +1,6 @@
 KNOWNBUG
 intervals2.c
---intervals
+--intervals --verify
 ^EXIT=0$
 ^SIGNAL=0$
 ^\[main.assertion.1\] file intervals2.c line 7 function main, assertion x > -10 && x < 100: SUCCESS$
diff --git a/regression/goto-analyzer/intervals3/test.desc b/regression/goto-analyzer/intervals3/test.desc
index 5db07df08a4..69ded2182ee 100644
--- a/regression/goto-analyzer/intervals3/test.desc
+++ b/regression/goto-analyzer/intervals3/test.desc
@@ -1,6 +1,6 @@
-CORE
+KNOWNBUG
 intervals3.c
---intervals
+--intervals --verify
 ^EXIT=0$
 ^SIGNAL=0$
 ^\[main.assertion.1\] file intervals3.c line 7 function main, assertion x > -10 || x < 100: SUCCESS$
diff --git a/regression/goto-analyzer/intervals4/test.desc b/regression/goto-analyzer/intervals4/test.desc
index 97d222012ad..2b725180e3f 100644
--- a/regression/goto-analyzer/intervals4/test.desc
+++ b/regression/goto-analyzer/intervals4/test.desc
@@ -1,6 +1,6 @@
 KNOWNBUG
 intervals4.c
---intervals
+--intervals --verify
 ^EXIT=0$
 ^SIGNAL=0$
 ^\[main.assertion.1\] file intervals4.c line 9 function main, assertion i >= 1 && i <= 2: SUCCESS$
diff --git a/regression/goto-analyzer/intervals5/test.desc b/regression/goto-analyzer/intervals5/test.desc
index 42554724e2d..eb64fbc13d1 100644
--- a/regression/goto-analyzer/intervals5/test.desc
+++ b/regression/goto-analyzer/intervals5/test.desc
@@ -1,6 +1,6 @@
-CORE
+KNOWNBUG
 intervals5.c
---intervals
+--intervals --verify
 ^EXIT=0$
 ^SIGNAL=0$
 ^\[main.assertion.1\] file intervals5.c line 9 function main, assertion i >= 1 || i <= 2: SUCCESS$
diff --git a/regression/goto-analyzer/intervals6/test.desc b/regression/goto-analyzer/intervals6/test.desc
index 14fd64f33dd..6e36b7948d2 100644
--- a/regression/goto-analyzer/intervals6/test.desc
+++ b/regression/goto-analyzer/intervals6/test.desc
@@ -1,8 +1,8 @@
-CORE
+FUTURE
 intervals6.c
---intervals
+--intervals --verify
 ^EXIT=0$
 ^SIGNAL=0$
-^\[main.assertion.1\] file intervals6.c line 7 function main, assertion x < -10 || x > 100: UNKNOWN$
+^\[main.assertion.1\] file intervals6.c line 7 function main, assertion x < -10 || x > 100: FAILURE (if reachable)$
 --
 ^warning: ignoring
diff --git a/regression/goto-analyzer/intervals7/test.desc b/regression/goto-analyzer/intervals7/test.desc
index aeeb24bd0a9..6a42b4a30ec 100644
--- a/regression/goto-analyzer/intervals7/test.desc
+++ b/regression/goto-analyzer/intervals7/test.desc
@@ -1,8 +1,8 @@
-CORE
+FUTURE
 intervals7.c
---intervals
+--intervals --verify
 ^EXIT=0$
 ^SIGNAL=0$
-^\[main.assertion.1\] file intervals7.c line 7 function main, assertion x < -10 && x > 100: UNKNOWN$
+^\[main.assertion.1\] file intervals7.c line 7 function main, assertion x < -10 && x > 100: FAILURE (if reachable)$
 --
 ^warning: ignoring
diff --git a/regression/goto-analyzer/intervals8/intervals8.c b/regression/goto-analyzer/intervals8/intervals8.c
new file mode 100644
index 00000000000..4128ac07ce5
--- /dev/null
+++ b/regression/goto-analyzer/intervals8/intervals8.c
@@ -0,0 +1,9 @@
+#include 
+
+int main(){
+  int x;
+  if (x > 0 && x < 20) {
+      assert(x < -10 && x < 100);
+  }
+  return 0;
+}
diff --git a/regression/goto-analyzer/intervals8/test.desc b/regression/goto-analyzer/intervals8/test.desc
new file mode 100644
index 00000000000..7500059a717
--- /dev/null
+++ b/regression/goto-analyzer/intervals8/test.desc
@@ -0,0 +1,8 @@
+FUTURE
+intervals8.c
+--intervals --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] file intervals8.c line 6 function main, assertion x < -10 && x < 100: FAILURE (if reachable)$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/intervals9/intervals9.c b/regression/goto-analyzer/intervals9/intervals9.c
new file mode 100644
index 00000000000..27739c7aa28
--- /dev/null
+++ b/regression/goto-analyzer/intervals9/intervals9.c
@@ -0,0 +1,12 @@
+#include 
+
+int main()
+{
+  int i;
+  
+  if(i>0)
+    if(i<3)
+      assert(i>=1 && i<=2);
+ 
+  return 0;
+} 
diff --git a/regression/goto-analyzer/intervals9/test.desc b/regression/goto-analyzer/intervals9/test.desc
new file mode 100644
index 00000000000..37c33b97288
--- /dev/null
+++ b/regression/goto-analyzer/intervals9/test.desc
@@ -0,0 +1,8 @@
+KNOWNBUG
+intervals9.c
+--intervals --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] file intervals9.c line 9 function main, assertion i>=1 && i<=2: SUCCESS$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-array-literal-const-fp-null/main.c b/regression/goto-analyzer/no-match-array-literal-const-fp-null/main.c
new file mode 100644
index 00000000000..93ed0af0d47
--- /dev/null
+++ b/regression/goto-analyzer/no-match-array-literal-const-fp-null/main.c
@@ -0,0 +1,31 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+const void_fp fp_tbl[] = {f2, NULL ,f4};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  fp_tbl[1]();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-array-literal-const-fp-null/test.desc b/regression/goto-analyzer/no-match-array-literal-const-fp-null/test.desc
new file mode 100644
index 00000000000..4786993cade
--- /dev/null
+++ b/regression/goto-analyzer/no-match-array-literal-const-fp-null/test.desc
@@ -0,0 +1,8 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+^Removing function pointers and virtual functions$
+^\s*ASSERT FALSE // invalid function pointer$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-array-const-pointer-const-fp-const-lost/main.c b/regression/goto-analyzer/no-match-const-array-const-pointer-const-fp-const-lost/main.c
new file mode 100644
index 00000000000..a17acab6166
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-array-const-pointer-const-fp-const-lost/main.c
@@ -0,0 +1,41 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp start_fp = f2;
+  const void_fp * const fp_tbl[] = { &start_fp, &start_fp, &start_fp };
+
+  // warning: loses const
+  void_fp * arr_ptr=fp_tbl[0];
+  (*arr_ptr) = f5;
+  arr_ptr++;
+  (*arr_ptr) = f5;
+
+  const void_fp * const fp = fp_tbl[1];
+
+
+  (*fp)();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-array-const-pointer-const-fp-const-lost/test.desc b/regression/goto-analyzer/no-match-const-array-const-pointer-const-fp-const-lost/test.desc
new file mode 100644
index 00000000000..9ac0520abde
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-array-const-pointer-const-fp-const-lost/test.desc
@@ -0,0 +1,16 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF \*fp == f1 THEN GOTO [0-9]$
+^\s*IF \*fp == f2 THEN GOTO [0-9]$
+^\s*IF \*fp == f3 THEN GOTO [0-9]$
+^\s*IF \*fp == f4 THEN GOTO [0-9]$
+^\s*IF \*fp == f5 THEN GOTO [0-9]$
+^\s*IF \*fp == f6 THEN GOTO [0-9]$
+^\s*IF \*fp == f7 THEN GOTO [0-9]$
+^\s*IF \*fp == f8 THEN GOTO [0-9]$
+^\s*IF \*fp == f9 THEN GOTO [0-9]$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-array-literal-const-fp-run-time/main.c b/regression/goto-analyzer/no-match-const-fp-array-literal-const-fp-run-time/main.c
new file mode 100644
index 00000000000..ee9ba95cb57
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-array-literal-const-fp-run-time/main.c
@@ -0,0 +1,36 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i, int j)
+{
+  const void_fp fp_tbl[] = {fp_all[i*2], fp_all[j+1]};
+  // Illegal:
+  //fp_tbl[1] = f4;
+  const void_fp fp = fp_tbl[1];
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i,0);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-array-literal-const-fp-run-time/test.desc b/regression/goto-analyzer/no-match-const-fp-array-literal-const-fp-run-time/test.desc
new file mode 100644
index 00000000000..997ec886207
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-array-literal-const-fp-run-time/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp-run-time/main.c b/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp-run-time/main.c
new file mode 100644
index 00000000000..fa1cf231a50
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp-run-time/main.c
@@ -0,0 +1,34 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i, int j)
+{
+  void_fp fp_tbl[] = {fp_all[i*2], fp_all[j+1]};
+  const void_fp fp = fp_tbl[1];
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i,0);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp-run-time/test.desc b/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp-run-time/test.desc
new file mode 100644
index 00000000000..997ec886207
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp-run-time/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp/main.c b/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp/main.c
new file mode 100644
index 00000000000..88b4edcf448
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp/main.c
@@ -0,0 +1,38 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+void_fp fp_tbl[] = {f2, f3, f4};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(void_fp fp, int i)
+{
+  // It is concievable this could be checked and seen the first value
+  // of the array is unchanged but is kind of a weird edge case.
+  fp_tbl[2] = fp;
+  const void_fp fp2 = fp_tbl[1];
+  fp2();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(fp_all[i+3], i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp/test.desc
new file mode 100644
index 00000000000..9c0926c2e7a
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-array-literal-non-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp2 == f1 THEN GOTO [0-9]$
+^\s*IF fp2 == f2 THEN GOTO [0-9]$
+^\s*IF fp2 == f3 THEN GOTO [0-9]$
+^\s*IF fp2 == f4 THEN GOTO [0-9]$
+^\s*IF fp2 == f5 THEN GOTO [0-9]$
+^\s*IF fp2 == f6 THEN GOTO [0-9]$
+^\s*IF fp2 == f7 THEN GOTO [0-9]$
+^\s*IF fp2 == f8 THEN GOTO [0-9]$
+^\s*IF fp2 == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-array-non-const-fp/main.c b/regression/goto-analyzer/no-match-const-fp-array-non-const-fp/main.c
new file mode 100644
index 00000000000..38d09cfb14e
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-array-non-const-fp/main.c
@@ -0,0 +1,36 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+void_fp fp_tbl[] = {f2, f3, f4};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(void_fp fp, int i)
+{
+  fp_tbl[2] = fp;
+  const void_fp fp2 = fp_tbl[2];
+  fp2();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(fp_all[i+3], i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-array-non-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-array-non-const-fp/test.desc
new file mode 100644
index 00000000000..9c0926c2e7a
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-array-non-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp2 == f1 THEN GOTO [0-9]$
+^\s*IF fp2 == f2 THEN GOTO [0-9]$
+^\s*IF fp2 == f3 THEN GOTO [0-9]$
+^\s*IF fp2 == f4 THEN GOTO [0-9]$
+^\s*IF fp2 == f5 THEN GOTO [0-9]$
+^\s*IF fp2 == f6 THEN GOTO [0-9]$
+^\s*IF fp2 == f7 THEN GOTO [0-9]$
+^\s*IF fp2 == f8 THEN GOTO [0-9]$
+^\s*IF fp2 == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-binary-op-const-lost/main.c b/regression/goto-analyzer/no-match-const-fp-binary-op-const-lost/main.c
new file mode 100644
index 00000000000..7f5c0ea3755
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-binary-op-const-lost/main.c
@@ -0,0 +1,35 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = f2;
+
+  // Warning: this loses const-ness of f2
+  void_fp * p2fp = 0 + ((void_fp*)&fp);
+  *p2fp = &f4;
+
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-binary-op-const-lost/test.desc b/regression/goto-analyzer/no-match-const-fp-binary-op-const-lost/test.desc
new file mode 100644
index 00000000000..e8357d911c6
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-binary-op-const-lost/test.desc
@@ -0,0 +1,16 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-const-array-index-lost/main.c b/regression/goto-analyzer/no-match-const-fp-const-array-index-lost/main.c
new file mode 100644
index 00000000000..b3dafeff777
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-array-index-lost/main.c
@@ -0,0 +1,40 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp_tbl[] = {f2, f3 ,f4};
+
+  // warning: loses const
+  void_fp * arr_ptr=&fp_tbl[0];
+  (*arr_ptr) = f5;
+  arr_ptr++;
+  (*arr_ptr) = f5;
+
+  const void_fp * const fp = &fp_tbl[1];
+
+
+  (*fp)();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-const-array-index-lost/test.desc b/regression/goto-analyzer/no-match-const-fp-const-array-index-lost/test.desc
new file mode 100644
index 00000000000..9ac0520abde
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-array-index-lost/test.desc
@@ -0,0 +1,16 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF \*fp == f1 THEN GOTO [0-9]$
+^\s*IF \*fp == f2 THEN GOTO [0-9]$
+^\s*IF \*fp == f3 THEN GOTO [0-9]$
+^\s*IF \*fp == f4 THEN GOTO [0-9]$
+^\s*IF \*fp == f5 THEN GOTO [0-9]$
+^\s*IF \*fp == f6 THEN GOTO [0-9]$
+^\s*IF \*fp == f7 THEN GOTO [0-9]$
+^\s*IF \*fp == f8 THEN GOTO [0-9]$
+^\s*IF \*fp == f9 THEN GOTO [0-9]$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-const-array-lost/main.c b/regression/goto-analyzer/no-match-const-fp-const-array-lost/main.c
new file mode 100644
index 00000000000..d27da78d0b7
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-array-lost/main.c
@@ -0,0 +1,40 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp_tbl[] = {f2, f3 ,f4};
+
+  // warning: loses const
+  void_fp * arr_ptr=fp_tbl;
+  (*arr_ptr) = f5;
+  arr_ptr++;
+  (*arr_ptr) = f5;
+
+  const void_fp * const fp = &fp_tbl[1];
+
+
+  (*fp)();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-const-array-lost/test.desc b/regression/goto-analyzer/no-match-const-fp-const-array-lost/test.desc
new file mode 100644
index 00000000000..9ac0520abde
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-array-lost/test.desc
@@ -0,0 +1,16 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF \*fp == f1 THEN GOTO [0-9]$
+^\s*IF \*fp == f2 THEN GOTO [0-9]$
+^\s*IF \*fp == f3 THEN GOTO [0-9]$
+^\s*IF \*fp == f4 THEN GOTO [0-9]$
+^\s*IF \*fp == f5 THEN GOTO [0-9]$
+^\s*IF \*fp == f6 THEN GOTO [0-9]$
+^\s*IF \*fp == f7 THEN GOTO [0-9]$
+^\s*IF \*fp == f8 THEN GOTO [0-9]$
+^\s*IF \*fp == f9 THEN GOTO [0-9]$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-const-cast/main.c b/regression/goto-analyzer/no-match-const-fp-const-cast/main.c
new file mode 100644
index 00000000000..b9bd141e6f0
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-cast/main.c
@@ -0,0 +1,35 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = f2;
+
+  // Warning: this loses const-ness of f2
+  void_fp * p2fp = (void_fp*)&fp;
+  *p2fp = &f4;
+
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-const-cast/test.desc b/regression/goto-analyzer/no-match-const-fp-const-cast/test.desc
new file mode 100644
index 00000000000..e8357d911c6
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-cast/test.desc
@@ -0,0 +1,16 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-const-fp-null/main.c b/regression/goto-analyzer/no-match-const-fp-const-fp-null/main.c
new file mode 100644
index 00000000000..67c501302a6
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-fp-null/main.c
@@ -0,0 +1,31 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = NULL;
+  const void_fp fp2 = fp;
+  fp2();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-const-fp-null/test.desc b/regression/goto-analyzer/no-match-const-fp-const-fp-null/test.desc
new file mode 100644
index 00000000000..4786993cade
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-fp-null/test.desc
@@ -0,0 +1,8 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+^Removing function pointers and virtual functions$
+^\s*ASSERT FALSE // invalid function pointer$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-const-lost/main.c b/regression/goto-analyzer/no-match-const-fp-const-lost/main.c
new file mode 100644
index 00000000000..d2724684066
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-lost/main.c
@@ -0,0 +1,35 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = f2;
+
+  // Warning: this loses const-ness of f2
+  void_fp * p2fp = &fp;
+  *p2fp = &f4;
+
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-const-lost/test.desc b/regression/goto-analyzer/no-match-const-fp-const-lost/test.desc
new file mode 100644
index 00000000000..e8357d911c6
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-lost/test.desc
@@ -0,0 +1,16 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-const-pointer-const-struct-const-fp-null/main.c b/regression/goto-analyzer/no-match-const-fp-const-pointer-const-struct-const-fp-null/main.c
new file mode 100644
index 00000000000..76671ef3829
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-pointer-const-struct-const-fp-null/main.c
@@ -0,0 +1,44 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+
+typedef struct fp_container
+{
+  int x;
+  const void_fp pointer;
+} fp_container;
+
+
+
+void func()
+{
+  const fp_container container = {.x = 10, .pointer = f3};
+  const fp_container container2 = {.x = 10, .pointer = f4};
+  const fp_container * const container_ptr = NULL;
+
+  // Illegal:
+  //container_ptr = &container2;
+  //container_ptr->pointer = f4;
+
+  container_ptr->pointer();
+}
+
+int main()
+{
+  func();
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-const-pointer-const-struct-const-fp-null/test.desc b/regression/goto-analyzer/no-match-const-fp-const-pointer-const-struct-const-fp-null/test.desc
new file mode 100644
index 00000000000..25b505c0a0f
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-pointer-const-struct-const-fp-null/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*ASSERT FALSE // invalid function pointer$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-const-pointer-non-const-struct-const-fp/main.c b/regression/goto-analyzer/no-match-const-fp-const-pointer-non-const-struct-const-fp/main.c
new file mode 100644
index 00000000000..3f55ff255dd
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-pointer-non-const-struct-const-fp/main.c
@@ -0,0 +1,47 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+struct state
+{
+  int x; // Mutable!
+  const void_fp go;
+};
+struct state thing = {0, &f2};
+struct state other_thing = {0, &f4};
+struct state * const pts = &thing;
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  // Illegal
+  //pts=&other_thing;
+  // thing.go=&f6;
+  thing = other_thing;
+  const void_fp fp = pts->go;
+
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-const-pointer-non-const-struct-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-const-pointer-non-const-struct-const-fp/test.desc
new file mode 100644
index 00000000000..997ec886207
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-const-pointer-non-const-struct-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-dereference-const-pointer-null/main.c b/regression/goto-analyzer/no-match-const-fp-dereference-const-pointer-null/main.c
new file mode 100644
index 00000000000..e4048adb8cb
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-dereference-const-pointer-null/main.c
@@ -0,0 +1,36 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = f3;
+  const void_fp fp2 = f4;
+  const void_fp* const p2fp = NULL;
+  // Illegal:
+  //p2fp = &fp2;
+  //fp = f5;
+  const void_fp final_fp=*p2fp;
+  final_fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-dereference-const-pointer-null/test.desc b/regression/goto-analyzer/no-match-const-fp-dereference-const-pointer-null/test.desc
new file mode 100644
index 00000000000..25b505c0a0f
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-dereference-const-pointer-null/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*ASSERT FALSE // invalid function pointer$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-dereference-non-const-pointer-const-fp/main.c b/regression/goto-analyzer/no-match-const-fp-dereference-non-const-pointer-const-fp/main.c
new file mode 100644
index 00000000000..30e4947c2d7
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-dereference-non-const-pointer-const-fp/main.c
@@ -0,0 +1,40 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = f3;
+  const void_fp fp2 = f4;
+  const void_fp* p2fp = &fp;
+
+
+  // Illegal:
+  //fp = f5;
+
+  // legal:
+  p2fp = &fp2;
+  const void_fp final_fp=*p2fp;
+  final_fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-dereference-non-const-pointer-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-dereference-non-const-pointer-const-fp/test.desc
new file mode 100644
index 00000000000..61a7ec29e6b
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-dereference-non-const-pointer-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF final_fp == f1 THEN GOTO [0-9]$
+^\s*IF final_fp == f2 THEN GOTO [0-9]$
+^\s*IF final_fp == f3 THEN GOTO [0-9]$
+^\s*IF final_fp == f4 THEN GOTO [0-9]$
+^\s*IF final_fp == f5 THEN GOTO [0-9]$
+^\s*IF final_fp == f6 THEN GOTO [0-9]$
+^\s*IF final_fp == f7 THEN GOTO [0-9]$
+^\s*IF final_fp == f8 THEN GOTO [0-9]$
+^\s*IF final_fp == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-dynamic-array-non-const-fp/main.c b/regression/goto-analyzer/no-match-const-fp-dynamic-array-non-const-fp/main.c
new file mode 100644
index 00000000000..d7d4820d29c
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-dynamic-array-non-const-fp/main.c
@@ -0,0 +1,39 @@
+#include 
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  void_fp * const fp_tbl= malloc(sizeof(void_fp) * 3);
+  fp_tbl[0]=f2;
+  fp_tbl[1]=f3;
+  fp_tbl[2]=f4;
+
+  // Illegal
+  //fp_tbl = malloc(sizeof(void_fp) * 10);
+
+  const void_fp fp = fp_tbl[1];
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-dynamic-array-non-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-dynamic-array-non-const-fp/test.desc
new file mode 100644
index 00000000000..997ec886207
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-dynamic-array-non-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-non-const-fp-direct-assignment/main.c b/regression/goto-analyzer/no-match-const-fp-non-const-fp-direct-assignment/main.c
new file mode 100644
index 00000000000..6c9ba5514e7
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-non-const-fp-direct-assignment/main.c
@@ -0,0 +1,32 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  void_fp fp = f2;
+  fp = f3;
+  const void_fp fp2 = fp;
+  fp2();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-non-const-fp-direct-assignment/test.desc b/regression/goto-analyzer/no-match-const-fp-non-const-fp-direct-assignment/test.desc
new file mode 100644
index 00000000000..13d0c5353ce
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-non-const-fp-direct-assignment/test.desc
@@ -0,0 +1,16 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+^Removing function pointers and virtual functions$
+^\s*IF fp2 == f1 THEN GOTO [0-9]$
+^\s*IF fp2 == f2 THEN GOTO [0-9]$
+^\s*IF fp2 == f3 THEN GOTO [0-9]$
+^\s*IF fp2 == f4 THEN GOTO [0-9]$
+^\s*IF fp2 == f5 THEN GOTO [0-9]$
+^\s*IF fp2 == f6 THEN GOTO [0-9]$
+^\s*IF fp2 == f7 THEN GOTO [0-9]$
+^\s*IF fp2 == f8 THEN GOTO [0-9]$
+^\s*IF fp2 == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-non-const-pointer-non-const-struct-const-fp/main.c b/regression/goto-analyzer/no-match-const-fp-non-const-pointer-non-const-struct-const-fp/main.c
new file mode 100644
index 00000000000..bb40b1a53c1
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-non-const-pointer-non-const-struct-const-fp/main.c
@@ -0,0 +1,47 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+struct state
+{
+  int x; // Mutable!
+  const void_fp go;
+};
+struct state thing = {0, &f2};
+struct state other_thing = {0, &f4};
+
+// This shouldn't work
+struct state * pts = &thing;
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  // This shouldn't work since
+  pts = &other_thing;
+  const void_fp fp = pts->go;
+  fp();
+}
+
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-non-const-pointer-non-const-struct-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-non-const-pointer-non-const-struct-const-fp/test.desc
new file mode 100644
index 00000000000..997ec886207
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-non-const-pointer-non-const-struct-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-non-const-struct-const-fp/main.c b/regression/goto-analyzer/no-match-const-fp-non-const-struct-const-fp/main.c
new file mode 100644
index 00000000000..ed86d4c39c6
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-non-const-struct-const-fp/main.c
@@ -0,0 +1,43 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+struct state
+{
+  int x; // Mutable!
+  const void_fp go;
+};
+struct state thing = {0, &f2};
+
+struct state other_thing = {0, &f4};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  thing = other_thing;
+  const void_fp fp = thing.go;
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-non-const-struct-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-non-const-struct-const-fp/test.desc
new file mode 100644
index 00000000000..997ec886207
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-non-const-struct-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-non-const-struct-non-const-fp/main.c b/regression/goto-analyzer/no-match-const-fp-non-const-struct-non-const-fp/main.c
new file mode 100644
index 00000000000..7d8b2584388
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-non-const-struct-non-const-fp/main.c
@@ -0,0 +1,43 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+struct action
+{
+  int x;
+  void_fp fun;
+};
+
+struct action rec = { .x = 4, .fun = f2 };
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  // Can mutate
+  rec.fun=f4;
+  const void_fp fp = rec.fun;
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-non-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/no-match-const-fp-non-const-struct-non-const-fp/test.desc
new file mode 100644
index 00000000000..997ec886207
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-non-const-struct-non-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-null/main.c b/regression/goto-analyzer/no-match-const-fp-null/main.c
new file mode 100644
index 00000000000..16c65f9f845
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-null/main.c
@@ -0,0 +1,30 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = NULL;
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-null/test.desc b/regression/goto-analyzer/no-match-const-fp-null/test.desc
new file mode 100644
index 00000000000..267ec2284f7
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-null/test.desc
@@ -0,0 +1,8 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*ASSERT FALSE // invalid function pointer$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-fp-ternerary-op-const-lost/main.c b/regression/goto-analyzer/no-match-const-fp-ternerary-op-const-lost/main.c
new file mode 100644
index 00000000000..ba5bcad694a
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-ternerary-op-const-lost/main.c
@@ -0,0 +1,36 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int x)
+{
+  const void_fp fp = f2;
+  void_fp non_const_fp = f7;
+
+  // Warning: this loses const-ness of f2
+  void_fp * p2fp = x > 0 ? ((void_fp*)&fp) : &non_const_fp;
+  *p2fp = &f4;
+
+  fp();
+}
+
+int main()
+{
+  func(1);
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-fp-ternerary-op-const-lost/test.desc b/regression/goto-analyzer/no-match-const-fp-ternerary-op-const-lost/test.desc
new file mode 100644
index 00000000000..e8357d911c6
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-fp-ternerary-op-const-lost/test.desc
@@ -0,0 +1,16 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-pointer-const-struct-const-fp-const-cast/main.c b/regression/goto-analyzer/no-match-const-pointer-const-struct-const-fp-const-cast/main.c
new file mode 100644
index 00000000000..b7b9e4d2b30
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-pointer-const-struct-const-fp-const-cast/main.c
@@ -0,0 +1,45 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+typedef struct fp_cc
+{
+  int x;
+  void_fp fp;
+} fp_cc;
+
+
+
+void func()
+{
+  const fp_cc container_container = { .fp = f2, .x = 4 };
+
+  const fp_cc * const container_pointer = &container_container;
+
+  fp_cc* container_pointer_modifier = (fp_cc*) container_pointer;
+  container_pointer_modifier->fp = f4;
+
+  // Illegal:
+  // container_container.container = &f4;
+
+  container_pointer->fp();
+}
+
+int main()
+{
+  func();
+}
diff --git a/regression/goto-analyzer/no-match-const-pointer-const-struct-const-fp-const-cast/test.desc b/regression/goto-analyzer/no-match-const-pointer-const-struct-const-fp-const-cast/test.desc
new file mode 100644
index 00000000000..2f4b2832b4d
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-pointer-const-struct-const-fp-const-cast/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF container_pointer->fp == f1 THEN GOTO [0-9]$
+^\s*IF container_pointer->fp == f2 THEN GOTO [0-9]$
+^\s*IF container_pointer->fp == f3 THEN GOTO [0-9]$
+^\s*IF container_pointer->fp == f4 THEN GOTO [0-9]$
+^\s*IF container_pointer->fp == f5 THEN GOTO [0-9]$
+^\s*IF container_pointer->fp == f6 THEN GOTO [0-9]$
+^\s*IF container_pointer->fp == f7 THEN GOTO [0-9]$
+^\s*IF container_pointer->fp == f8 THEN GOTO [0-9]$
+^\s*IF container_pointer->fp == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-pointer-non-const-struct-const-fp/main.c b/regression/goto-analyzer/no-match-const-pointer-non-const-struct-const-fp/main.c
new file mode 100644
index 00000000000..bf4bb45d094
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-pointer-non-const-struct-const-fp/main.c
@@ -0,0 +1,43 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+struct state
+{
+  int x; // Mutable!
+  const void_fp go;
+};
+struct state thing = {0, &f2};
+struct state other_thing = {0, &f4};
+struct state const * const pts = &thing;
+
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  thing = other_thing;
+  pts->go();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-pointer-non-const-struct-const-fp/test.desc b/regression/goto-analyzer/no-match-const-pointer-non-const-struct-const-fp/test.desc
new file mode 100644
index 00000000000..2760fadd576
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-pointer-non-const-struct-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF pts->go == f1 THEN GOTO [0-9]$
+^\s*IF pts->go == f2 THEN GOTO [0-9]$
+^\s*IF pts->go == f3 THEN GOTO [0-9]$
+^\s*IF pts->go == f4 THEN GOTO [0-9]$
+^\s*IF pts->go == f5 THEN GOTO [0-9]$
+^\s*IF pts->go == f6 THEN GOTO [0-9]$
+^\s*IF pts->go == f7 THEN GOTO [0-9]$
+^\s*IF pts->go == f8 THEN GOTO [0-9]$
+^\s*IF pts->go == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-const-struct-non-const-fp-null/main.c b/regression/goto-analyzer/no-match-const-struct-non-const-fp-null/main.c
new file mode 100644
index 00000000000..6e24a0d8d4c
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-struct-non-const-fp-null/main.c
@@ -0,0 +1,40 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+struct action
+{
+  int x;
+  const void_fp fun;
+};
+
+const struct action rec = { .x = 4, .fun = NULL };
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  rec.fun();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-const-struct-non-const-fp-null/test.desc b/regression/goto-analyzer/no-match-const-struct-non-const-fp-null/test.desc
new file mode 100644
index 00000000000..25b505c0a0f
--- /dev/null
+++ b/regression/goto-analyzer/no-match-const-struct-non-const-fp-null/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*ASSERT FALSE // invalid function pointer$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/main.c b/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/main.c
new file mode 100644
index 00000000000..5d857ffcfe7
--- /dev/null
+++ b/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/main.c
@@ -0,0 +1,52 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+typedef struct fp_container
+{
+  int x;
+  const void_fp* const fp_tbl[3];
+} fp_container;
+
+
+
+void func()
+{
+  void_fp f2meta = &f2;
+  void_fp f3meta = &f3;
+  void_fp f4meta = &f4;
+
+  void_fp f5meta = &f5;
+  void_fp f6meta = &f6;
+  void_fp f7meta = &f7;
+
+  const fp_container container = { .x = 4, .fp_tbl = {&f2meta ,&f3meta, &f4meta} };
+  const fp_container container2 = { .x = 5, .fp_tbl = {&f5meta ,&f6meta, &f7meta} };
+
+  f3meta = &f5;
+  // Illegal:
+  // container.fp_tbl = alternatate_fp_tbl;
+  // container.fp_tbl[1] = f4;
+  const fp_container * const container_ptr=&container;
+  //container_ptr=&container2;
+  (*container_ptr->fp_tbl[1])();
+}
+
+int main()
+{
+  func();
+}
diff --git a/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/test.desc b/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/test.desc
new file mode 100644
index 00000000000..7e0aca75523
--- /dev/null
+++ b/regression/goto-analyzer/no-match-dereference-const-pointer-const-array-literal-pointer-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f1 THEN GOTO [0-9]$
+^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f2 THEN GOTO [0-9]$
+^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f3 THEN GOTO [0-9]$
+^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f4 THEN GOTO [0-9]$
+^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f5 THEN GOTO [0-9]$
+^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f6 THEN GOTO [0-9]$
+^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f7 THEN GOTO [0-9]$
+^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f8 THEN GOTO [0-9]$
+^\s*IF \*container_ptr->fp_tbl\[\(signed long int\)1\] == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-dereference-non-const-struct-const-pointer-const-fp/main.c b/regression/goto-analyzer/no-match-dereference-non-const-struct-const-pointer-const-fp/main.c
new file mode 100644
index 00000000000..b0be4e4837c
--- /dev/null
+++ b/regression/goto-analyzer/no-match-dereference-non-const-struct-const-pointer-const-fp/main.c
@@ -0,0 +1,46 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+typedef struct fp_cc
+{
+  int x;
+  const void_fp * const container;
+} fp_cc;
+
+
+
+void func()
+{
+  const void_fp meta_fp = &f3;
+  const void_fp meta_fp2 = &f4;
+
+  fp_cc container_container2 = { .container = &meta_fp2, .x = 4 };
+  fp_cc container_container = { .container = &meta_fp, .x = 4 };
+  container_container = container_container2;
+
+  // Illegal:
+  //meta_fp = &f4;
+  //container_container.container = &f4;
+
+  (*container_container.container)();
+}
+
+int main()
+{
+  func();
+}
diff --git a/regression/goto-analyzer/no-match-dereference-non-const-struct-const-pointer-const-fp/test.desc b/regression/goto-analyzer/no-match-dereference-non-const-struct-const-pointer-const-fp/test.desc
new file mode 100644
index 00000000000..f55defde97b
--- /dev/null
+++ b/regression/goto-analyzer/no-match-dereference-non-const-struct-const-pointer-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF \*container_container\.container == f1 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f2 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f3 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f4 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f5 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f6 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f7 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f8 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-dereference-non-const-struct-non-const-pointer-const-fp/main.c b/regression/goto-analyzer/no-match-dereference-non-const-struct-non-const-pointer-const-fp/main.c
new file mode 100644
index 00000000000..28110c56d01
--- /dev/null
+++ b/regression/goto-analyzer/no-match-dereference-non-const-struct-non-const-pointer-const-fp/main.c
@@ -0,0 +1,43 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+typedef struct fp_cc
+{
+  int x;
+  const void_fp * container;
+} fp_cc;
+
+
+
+void func()
+{
+  const void_fp meta_fp = &f3;
+  const void_fp meta_fp2 = &f4;
+  fp_cc container_container = { .container = &meta_fp, .x = 4 };
+
+  // Illegal:
+  //meta_fp = &f4;
+  container_container.container = &meta_fp2;
+
+  (*container_container.container)();
+}
+
+int main()
+{
+  func();
+}
diff --git a/regression/goto-analyzer/no-match-dereference-non-const-struct-non-const-pointer-const-fp/test.desc b/regression/goto-analyzer/no-match-dereference-non-const-struct-non-const-pointer-const-fp/test.desc
new file mode 100644
index 00000000000..f55defde97b
--- /dev/null
+++ b/regression/goto-analyzer/no-match-dereference-non-const-struct-non-const-pointer-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF \*container_container\.container == f1 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f2 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f3 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f4 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f5 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f6 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f7 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f8 THEN GOTO [0-9]$
+^\s*IF \*container_container\.container == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-non-const-fp-const-fp-direct-assignment/main.c b/regression/goto-analyzer/no-match-non-const-fp-const-fp-direct-assignment/main.c
new file mode 100644
index 00000000000..4487db8b047
--- /dev/null
+++ b/regression/goto-analyzer/no-match-non-const-fp-const-fp-direct-assignment/main.c
@@ -0,0 +1,33 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = f2;
+  const void_fp fp3 = f4;
+  void_fp fp2 = fp;
+  fp2 = fp3;
+  fp2();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-non-const-fp-const-fp-direct-assignment/test.desc b/regression/goto-analyzer/no-match-non-const-fp-const-fp-direct-assignment/test.desc
new file mode 100644
index 00000000000..13d0c5353ce
--- /dev/null
+++ b/regression/goto-analyzer/no-match-non-const-fp-const-fp-direct-assignment/test.desc
@@ -0,0 +1,16 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+^Removing function pointers and virtual functions$
+^\s*IF fp2 == f1 THEN GOTO [0-9]$
+^\s*IF fp2 == f2 THEN GOTO [0-9]$
+^\s*IF fp2 == f3 THEN GOTO [0-9]$
+^\s*IF fp2 == f4 THEN GOTO [0-9]$
+^\s*IF fp2 == f5 THEN GOTO [0-9]$
+^\s*IF fp2 == f6 THEN GOTO [0-9]$
+^\s*IF fp2 == f7 THEN GOTO [0-9]$
+^\s*IF fp2 == f8 THEN GOTO [0-9]$
+^\s*IF fp2 == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-non-const-fp/main.c b/regression/goto-analyzer/no-match-non-const-fp/main.c
new file mode 100644
index 00000000000..80c8c863ff5
--- /dev/null
+++ b/regression/goto-analyzer/no-match-non-const-fp/main.c
@@ -0,0 +1,31 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  void_fp fp = f2;
+  fp = f3;
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-non-const-fp/test.desc b/regression/goto-analyzer/no-match-non-const-fp/test.desc
new file mode 100644
index 00000000000..997ec886207
--- /dev/null
+++ b/regression/goto-analyzer/no-match-non-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-parameter-const-fp/main.c b/regression/goto-analyzer/no-match-parameter-const-fp/main.c
new file mode 100644
index 00000000000..23e73aabdc0
--- /dev/null
+++ b/regression/goto-analyzer/no-match-parameter-const-fp/main.c
@@ -0,0 +1,32 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(const void_fp fp)
+{
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(fp_all[i]);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-parameter-const-fp/test.desc b/regression/goto-analyzer/no-match-parameter-const-fp/test.desc
new file mode 100644
index 00000000000..997ec886207
--- /dev/null
+++ b/regression/goto-analyzer/no-match-parameter-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-parameter-fp/main.c b/regression/goto-analyzer/no-match-parameter-fp/main.c
new file mode 100644
index 00000000000..332df257368
--- /dev/null
+++ b/regression/goto-analyzer/no-match-parameter-fp/main.c
@@ -0,0 +1,32 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(void_fp fp)
+{
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(fp_all[i]);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/no-match-parameter-fp/test.desc b/regression/goto-analyzer/no-match-parameter-fp/test.desc
new file mode 100644
index 00000000000..997ec886207
--- /dev/null
+++ b/regression/goto-analyzer/no-match-parameter-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/main.c b/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/main.c
new file mode 100644
index 00000000000..c9d632f43b9
--- /dev/null
+++ b/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/main.c
@@ -0,0 +1,42 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+typedef struct fp_container
+{
+  void_fp fp_tbl[3];
+} fp_container;
+
+
+
+void func()
+{
+  const fp_container container = { .fp_tbl = {f2 ,f3, f4} };
+  const void_fp alternatate_fp_tbl[] = {f5 ,f6, f7};
+  const fp_container container2 = { .fp_tbl = {f5 ,f6, f7} };
+  // Illegal:
+  // container.fp_tbl = alternatate_fp_tbl;
+  // container.fp_tbl[1] = f4;
+  const fp_container *container_ptr=&container;
+  container_ptr=&container2;
+  container_ptr->fp_tbl[1]();
+}
+
+int main()
+{
+  func();
+}
diff --git a/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/test.desc b/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/test.desc
new file mode 100644
index 00000000000..83a4d98d9f4
--- /dev/null
+++ b/regression/goto-analyzer/no-match-pointer-const-struct-array-literal-non-const-fp/test.desc
@@ -0,0 +1,17 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f1 THEN GOTO [0-9]$
+^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f2 THEN GOTO [0-9]$
+^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f3 THEN GOTO [0-9]$
+^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f4 THEN GOTO [0-9]$
+^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f5 THEN GOTO [0-9]$
+^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f6 THEN GOTO [0-9]$
+^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f7 THEN GOTO [0-9]$
+^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f8 THEN GOTO [0-9]$
+^\s*IF container_ptr->fp_tbl\[\(signed long int\)1\] == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-array-calculation-const-fp/main.c b/regression/goto-analyzer/precise-array-calculation-const-fp/main.c
new file mode 100644
index 00000000000..a61d95186aa
--- /dev/null
+++ b/regression/goto-analyzer/precise-array-calculation-const-fp/main.c
@@ -0,0 +1,32 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+const void_fp fp_tbl[] = {f2, f3 ,f4};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const short short_const_variable=1;
+  fp_tbl[(signed long int)((signed int)short_const_variable & 0x1)]();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-array-calculation-const-fp/test.desc b/regression/goto-analyzer/precise-array-calculation-const-fp/test.desc
new file mode 100644
index 00000000000..fad0e6c7a1d
--- /dev/null
+++ b/regression/goto-analyzer/precise-array-calculation-const-fp/test.desc
@@ -0,0 +1,8 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-array-literal-const-fp/main.c b/regression/goto-analyzer/precise-array-literal-const-fp/main.c
new file mode 100644
index 00000000000..55dab779802
--- /dev/null
+++ b/regression/goto-analyzer/precise-array-literal-const-fp/main.c
@@ -0,0 +1,31 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+const void_fp fp_tbl[] = {f2, f3 ,f4};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  fp_tbl[1]();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-array-literal-const-fp/test.desc b/regression/goto-analyzer/precise-array-literal-const-fp/test.desc
new file mode 100644
index 00000000000..fad0e6c7a1d
--- /dev/null
+++ b/regression/goto-analyzer/precise-array-literal-const-fp/test.desc
@@ -0,0 +1,8 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-const-fp-array-const-variable-const-fp/main.c b/regression/goto-analyzer/precise-const-fp-array-const-variable-const-fp/main.c
new file mode 100644
index 00000000000..c2465dcb695
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-array-const-variable-const-fp/main.c
@@ -0,0 +1,33 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+const void_fp fp_tbl[] = {f2, f3 ,f4};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const int x = 1;
+  const void_fp fp = fp_tbl[x];
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-const-fp-array-const-variable-const-fp/test.desc b/regression/goto-analyzer/precise-const-fp-array-const-variable-const-fp/test.desc
new file mode 100644
index 00000000000..fad0e6c7a1d
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-array-const-variable-const-fp/test.desc
@@ -0,0 +1,8 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-const-fp-array-literal-const-fp-run-time/main.c b/regression/goto-analyzer/precise-const-fp-array-literal-const-fp-run-time/main.c
new file mode 100644
index 00000000000..59d51313fde
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-array-literal-const-fp-run-time/main.c
@@ -0,0 +1,32 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp_tbl[] = {f2, f3};
+  // Illegal:
+  //fp_tbl[1] = f4;
+  const void_fp fp = fp_tbl[1];
+  fp();
+}
+
+int main()
+{
+  func();
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-const-fp-array-literal-const-fp-run-time/test.desc b/regression/goto-analyzer/precise-const-fp-array-literal-const-fp-run-time/test.desc
new file mode 100644
index 00000000000..6c7de56a1a0
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-array-literal-const-fp-run-time/test.desc
@@ -0,0 +1,8 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-const-fp-array-literal-const-fp/main.c b/regression/goto-analyzer/precise-const-fp-array-literal-const-fp/main.c
new file mode 100644
index 00000000000..2e9cb8cc4df
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-array-literal-const-fp/main.c
@@ -0,0 +1,32 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+const void_fp fp_tbl[] = {f2, f3 ,f4};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = fp_tbl[1];
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-const-fp-array-literal-const-fp/test.desc b/regression/goto-analyzer/precise-const-fp-array-literal-const-fp/test.desc
new file mode 100644
index 00000000000..fad0e6c7a1d
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-array-literal-const-fp/test.desc
@@ -0,0 +1,8 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-const-fp-array-literal-const-struct-non-const-fp/main.c b/regression/goto-analyzer/precise-const-fp-array-literal-const-struct-non-const-fp/main.c
new file mode 100644
index 00000000000..26f13fc4c28
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-array-literal-const-struct-non-const-fp/main.c
@@ -0,0 +1,52 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+struct stable
+{
+  int x;
+  void (*fp)(void);
+};
+
+const struct stable stable_table [3] =
+{
+  { 1, f2 },
+  { 2, f3 },
+  { 3, f4 }
+};
+
+const struct stable another_table = { 4, f5 };
+
+
+void func(int i)
+{
+  const void_fp fp = stable_table[1].fp;
+
+  // Illegal
+  // stable_table[1] = another_table;
+  // stable_table[1].fp = f5;
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-const-fp-array-literal-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/precise-const-fp-array-literal-const-struct-non-const-fp/test.desc
new file mode 100644
index 00000000000..2eff811f4bc
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-array-literal-const-struct-non-const-fp/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-const-fp-array-variable-const-pointer-const-struct-non-const-fp/main.c b/regression/goto-analyzer/precise-const-fp-array-variable-const-pointer-const-struct-non-const-fp/main.c
new file mode 100644
index 00000000000..c61a7a32499
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-array-variable-const-pointer-const-struct-non-const-fp/main.c
@@ -0,0 +1,49 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+struct action
+{
+  int x;
+  void_fp fun;
+};
+
+const struct action rec = { .x = 4, .fun = f2 };
+
+const struct action * const action_list[4] =
+{
+  &rec,
+  &rec,
+  &rec,
+  &rec
+};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  const void_fp fp = action_list[i]->fun;
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<4;i++)
+{
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/precise-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc
new file mode 100644
index 00000000000..eb1e2781ef1
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-array-variable-const-pointer-const-struct-non-const-fp/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f2\(\);
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-const-fp-const-fp/main.c b/regression/goto-analyzer/precise-const-fp-const-fp/main.c
new file mode 100644
index 00000000000..a1efb8e0934
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-const-fp/main.c
@@ -0,0 +1,31 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = f2;
+  const void_fp fp2 = fp;
+  fp2();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-const-fp-const-fp/test.desc b/regression/goto-analyzer/precise-const-fp-const-fp/test.desc
new file mode 100644
index 00000000000..40361f6ccc2
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-const-fp/test.desc
@@ -0,0 +1,8 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+^Removing function pointers and virtual functions$
+^\s*f2\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-const-fp-const-struct-const-array-literal-fp/main.c b/regression/goto-analyzer/precise-const-fp-const-struct-const-array-literal-fp/main.c
new file mode 100644
index 00000000000..8a05a9b7d4c
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-const-struct-const-array-literal-fp/main.c
@@ -0,0 +1,39 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+typedef struct fp_container
+{
+  const void_fp fp_tbl[3];
+} fp_container;
+
+
+
+void func()
+{
+  const fp_container container = { .fp_tbl = {f2 ,f3, f4} };
+  const fp_container container2 = { .fp_tbl = {f5 ,f6, f7} };
+  // Illegal:
+  //container = container2;
+  const void_fp fp = container.fp_tbl[1];
+  fp();
+}
+
+int main()
+{
+  func();
+}
diff --git a/regression/goto-analyzer/precise-const-fp-const-struct-const-array-literal-fp/test.desc b/regression/goto-analyzer/precise-const-fp-const-struct-const-array-literal-fp/test.desc
new file mode 100644
index 00000000000..2eff811f4bc
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-const-struct-const-array-literal-fp/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-const-fp-const-struct-non-const-array-literal-fp/main.c b/regression/goto-analyzer/precise-const-fp-const-struct-non-const-array-literal-fp/main.c
new file mode 100644
index 00000000000..bc4ffead00e
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-const-struct-non-const-array-literal-fp/main.c
@@ -0,0 +1,45 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+typedef struct fp_container
+{
+  int x;
+  void_fp fp_tbl[3];
+} fp_container;
+
+
+
+void func()
+{
+  const fp_container container = { .x = 4, .fp_tbl = {f2 ,f3, f4} };
+  fp_container container2 = { .x = 5, .fp_tbl = {f5 ,f6, f7} };
+  const void_fp alternatate_fp_tbl[] = {f5 ,f6, f7};
+  // Illegal:
+  // container = container2;
+  // container.fp_tbl = alternatate_fp_tbl;
+  // container.fp_tbl[1] = f4;
+  const void_fp fp = container.fp_tbl[1];
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-const-fp-const-struct-non-const-array-literal-fp/test.desc b/regression/goto-analyzer/precise-const-fp-const-struct-non-const-array-literal-fp/test.desc
new file mode 100644
index 00000000000..2eff811f4bc
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-const-struct-non-const-array-literal-fp/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-const-fp-const-struct-non-const-fp/main.c b/regression/goto-analyzer/precise-const-fp-const-struct-non-const-fp/main.c
new file mode 100644
index 00000000000..7c3bed93919
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-const-struct-non-const-fp/main.c
@@ -0,0 +1,44 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+struct action
+{
+  int x;
+  void_fp fun;
+};
+
+const struct action rec = { .x = 4, .fun = f2 };
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+
+  // Illegal:
+  //rec.fun = &f5;
+  const void_fp fp = rec.fun;
+  fp();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-const-fp-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/precise-const-fp-const-struct-non-const-fp/test.desc
new file mode 100644
index 00000000000..eb1e2781ef1
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-const-struct-non-const-fp/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f2\(\);
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-const-fp-dereference-const-pointer-const-fp/main.c b/regression/goto-analyzer/precise-const-fp-dereference-const-pointer-const-fp/main.c
new file mode 100644
index 00000000000..efeb3b35d80
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-dereference-const-pointer-const-fp/main.c
@@ -0,0 +1,36 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = f3;
+  const void_fp fp2 = f4;
+  const void_fp* const p2fp = &fp;
+  // Illegal:
+  //p2fp = &fp2;
+  //fp = f5;
+  const void_fp final_fp=*p2fp;
+  final_fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-const-fp-dereference-const-pointer-const-fp/test.desc b/regression/goto-analyzer/precise-const-fp-dereference-const-pointer-const-fp/test.desc
new file mode 100644
index 00000000000..2eff811f4bc
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp-dereference-const-pointer-const-fp/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-const-fp/main.c b/regression/goto-analyzer/precise-const-fp/main.c
new file mode 100644
index 00000000000..b4002c94e5e
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp/main.c
@@ -0,0 +1,30 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = f2;
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-const-fp/test.desc b/regression/goto-analyzer/precise-const-fp/test.desc
new file mode 100644
index 00000000000..ef4cf690b60
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-fp/test.desc
@@ -0,0 +1,8 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f2\(\);
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-const-pointer-const-struct-fp/main.c b/regression/goto-analyzer/precise-const-pointer-const-struct-fp/main.c
new file mode 100644
index 00000000000..e1671666b2b
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-pointer-const-struct-fp/main.c
@@ -0,0 +1,43 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+typedef struct fp_cc
+{
+  int x;
+  void_fp fp;
+} fp_cc;
+
+
+
+void func()
+{
+  const fp_cc container_container = { .fp = f2, .x = 4 };
+
+  const fp_cc * const container_pointer = &container_container;
+
+  // Illegal:
+  //meta_fp = &f4;
+  //container_container.container = &f4;
+
+  container_pointer->fp();
+}
+
+int main()
+{
+  func();
+}
diff --git a/regression/goto-analyzer/precise-const-pointer-const-struct-fp/test.desc b/regression/goto-analyzer/precise-const-pointer-const-struct-fp/test.desc
new file mode 100644
index 00000000000..0de6942ba42
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-pointer-const-struct-fp/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f2\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-const-struct-non-const-fp/main.c b/regression/goto-analyzer/precise-const-struct-non-const-fp/main.c
new file mode 100644
index 00000000000..150ea314914
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-struct-non-const-fp/main.c
@@ -0,0 +1,40 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+struct action
+{
+  int x;
+  void_fp fun;
+};
+
+const struct action rec = { .x = 4, .fun = f2 };
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  rec.fun();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-const-struct-non-const-fp/test.desc b/regression/goto-analyzer/precise-const-struct-non-const-fp/test.desc
new file mode 100644
index 00000000000..eb1e2781ef1
--- /dev/null
+++ b/regression/goto-analyzer/precise-const-struct-non-const-fp/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f2\(\);
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-derefence-const-pointer-const-fp/main.c b/regression/goto-analyzer/precise-derefence-const-pointer-const-fp/main.c
new file mode 100644
index 00000000000..78901cc6405
--- /dev/null
+++ b/regression/goto-analyzer/precise-derefence-const-pointer-const-fp/main.c
@@ -0,0 +1,35 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = f3;
+  const void_fp fp2 = f4;
+  const void_fp* const p2fp = &fp;
+  // Illegal:
+  //p2fp = &fp2;
+  //fp = f5;
+  (*p2fp)();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-derefence-const-pointer-const-fp/test.desc b/regression/goto-analyzer/precise-derefence-const-pointer-const-fp/test.desc
new file mode 100644
index 00000000000..2eff811f4bc
--- /dev/null
+++ b/regression/goto-analyzer/precise-derefence-const-pointer-const-fp/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-derefence/main.c b/regression/goto-analyzer/precise-derefence/main.c
new file mode 100644
index 00000000000..d3bc8a2bc35
--- /dev/null
+++ b/regression/goto-analyzer/precise-derefence/main.c
@@ -0,0 +1,31 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  // There isn't an obvious reason to write this code, but perhaps some
+  // code can get transformed into this so we should still handle it.
+  (*(&f2))();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-derefence/test.desc b/regression/goto-analyzer/precise-derefence/test.desc
new file mode 100644
index 00000000000..ef4cf690b60
--- /dev/null
+++ b/regression/goto-analyzer/precise-derefence/test.desc
@@ -0,0 +1,8 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f2\(\);
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-dereference-address-pointer-const-fp/main.c b/regression/goto-analyzer/precise-dereference-address-pointer-const-fp/main.c
new file mode 100644
index 00000000000..e0246369f7b
--- /dev/null
+++ b/regression/goto-analyzer/precise-dereference-address-pointer-const-fp/main.c
@@ -0,0 +1,30 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = f3;
+  (*(&fp))();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/precise-dereference-address-pointer-const-fp/test.desc b/regression/goto-analyzer/precise-dereference-address-pointer-const-fp/test.desc
new file mode 100644
index 00000000000..2eff811f4bc
--- /dev/null
+++ b/regression/goto-analyzer/precise-dereference-address-pointer-const-fp/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-fp/main.c b/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-fp/main.c
new file mode 100644
index 00000000000..c8694d74a08
--- /dev/null
+++ b/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-fp/main.c
@@ -0,0 +1,42 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+typedef struct fp_cc
+{
+  int x;
+  const void_fp * const container;
+} fp_cc;
+
+
+
+void func()
+{
+  const void_fp meta_fp = &f3;
+  const fp_cc container_container = { .container = &meta_fp, .x = 4 };
+
+  // Illegal:
+  //meta_fp = &f4;
+  //container_container.container = &f4;
+
+  (*container_container.container)();
+}
+
+int main()
+{
+  func();
+}
diff --git a/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-fp/test.desc b/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-fp/test.desc
new file mode 100644
index 00000000000..2eff811f4bc
--- /dev/null
+++ b/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-fp/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-struct-const-fp/main.c b/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-struct-const-fp/main.c
new file mode 100644
index 00000000000..4f00ca80765
--- /dev/null
+++ b/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-struct-const-fp/main.c
@@ -0,0 +1,49 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+typedef struct fp_container
+{
+  int y;
+  const void_fp pointer;
+} fp_container;
+
+typedef struct fp_cc
+{
+  int x;
+  const fp_container * const container;
+} fp_cc;
+
+
+
+void func()
+{
+  const fp_container container = {.y = 10, .pointer = f3};
+  const fp_container container2 = {.y = 10, .pointer = f4};
+  const fp_cc container_container = { .container = &container, .x = 4 };
+
+  // Illegal:
+  //container_container.container = &container2;
+  //container.pointer = f4;
+
+  (*container_container.container).pointer();
+}
+
+int main()
+{
+  func();
+}
diff --git a/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-struct-const-fp/test.desc b/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-struct-const-fp/test.desc
new file mode 100644
index 00000000000..2eff811f4bc
--- /dev/null
+++ b/regression/goto-analyzer/precise-dereference-const-struct-const-pointer-const-struct-const-fp/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/precise-dereference-const-struct-pointer-const-fp/main.c b/regression/goto-analyzer/precise-dereference-const-struct-pointer-const-fp/main.c
new file mode 100644
index 00000000000..1d562a42dc8
--- /dev/null
+++ b/regression/goto-analyzer/precise-dereference-const-struct-pointer-const-fp/main.c
@@ -0,0 +1,42 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+typedef struct fp_cc
+{
+  int x;
+  const void_fp * container;
+} fp_cc;
+
+
+
+void func()
+{
+  const void_fp meta_fp = &f3;
+  const fp_cc container_container = { .container = &meta_fp, .x = 4 };
+
+  // Illegal:
+  //meta_fp = &f4;
+  //container_container.container = &f4;
+
+  (*container_container.container)();
+}
+
+int main()
+{
+  func();
+}
diff --git a/regression/goto-analyzer/precise-dereference-const-struct-pointer-const-fp/test.desc b/regression/goto-analyzer/precise-dereference-const-struct-pointer-const-fp/test.desc
new file mode 100644
index 00000000000..2eff811f4bc
--- /dev/null
+++ b/regression/goto-analyzer/precise-dereference-const-struct-pointer-const-fp/test.desc
@@ -0,0 +1,9 @@
+CORE
+main.c
+--show-goto-functions --verbosity 10 --pointer-check
+
+^Removing function pointers and virtual functions$
+^\s*f3\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/array_of_array_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/array_of_array_sensitivity_tests.c
new file mode 100644
index 00000000000..63af187ade2
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/array_of_array_sensitivity_tests.c
@@ -0,0 +1,150 @@
+#include 
+
+int main(int argc, char *argv[])
+{
+  // A uniform constant array
+  int a[3][3]={{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
+  // A non-uniform constant array
+  int b[3][3]={{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
+
+  // Test if we can represent uniform constant arrays
+  assert(a[1][2]==0);
+  assert(a[1][2]==1);
+
+  // Test if we can represent constant arrays which aren't uniform
+  assert(b[1][2]==5);
+  assert(b[1][2]==0);
+
+  // Test alternative syntax for accessing an array value
+  assert(*(b[1]+2)==5);
+  assert(*(b[1]+2)==0);
+  assert((*(b+1))[2]==5);
+  assert((*(b+1))[2]==0);
+  assert(*(*(b+1)+2)==5);
+  assert(*(*(b+1)+2)==0);
+  assert(1[b][2]==5);
+  assert(1[b][2]==0);
+  assert(*(1[b]+2)==5);
+  assert(*(1[b]+2)==0);
+  assert((*(1+b))[2]==5);
+  assert((*(1+b))[2]==0);
+  assert(*(*(1+b)+2)==5);
+  assert(*(*(1+b)+2)==0);
+  assert(2[1[b]]==5);
+  assert(2[1[b]]==0);
+  assert(*(2+1[b])==5);
+  assert(*(2+1[b])==0);
+  assert(*(2+*(1+b))==5);
+  assert(*(2+*(1+b))==0);
+
+  // Test how well we can deal with merging for an array value when there is one
+  // possible value
+  if(argc>2)
+  {
+    a[0][1]=0;
+  }
+  assert(a[0][1]==0);
+  assert(a[0][1]==1);
+  assert(a[0][2]==0);
+
+  // Test how well we can deal with merging for an array value when there are
+  // two possible values
+  if(argc>2)
+  {
+    b[0][1]=2;
+  }
+  assert(b[0][1]==2);
+  assert(b[0][1]==3);
+  assert(b[0][2]==2);
+
+  // Reset this change to ensure tests later work as expected
+  b[0][1]=1;
+
+  // The variables i, j and k will be used as indexes into arrays of size 3.
+  // They all require merging paths in the CFG. For i there is only one value on
+  // both paths, which is a valid index. The rest can each take two different
+  // values. For j both of these values are valid indexes. For k one is and one
+  // isn't.
+  int i=0;
+  int j=0;
+  int k=0;
+  if(argc>3)
+  {
+    i=0;
+    j=1;
+    k=100;
+  }
+
+  // Test how well we can deal with merging for an index on a uniform array when
+  // the index has one possible value
+  assert(a[i][1]==0);
+  assert(a[i][1]==1);
+  assert(a[1][i]==0);
+  assert(a[1][i]==1);
+  assert(a[i][i]==0);
+  assert(a[i][i]==1);
+
+  // Test how well we can deal with merging for an index on a uniform array when
+  // the index has two possible values
+  assert(a[j][1]==0);
+  assert(a[j][1]==1);
+  assert(a[1][j]==0);
+  assert(a[1][j]==1);
+  assert(a[j][j]==0);
+  assert(a[j][j]==1);
+
+  // Test how well we can deal with merging for an index on a non-uniform array
+
+  assert(b[i][1]==1);
+  assert(b[i][1]==11);
+  assert(b[1][i]==3);
+  assert(b[1][i]==11);
+  assert(b[i][i]==0);
+  assert(b[i][i]==11);
+
+  // Test how well we can deal with merging for an index on a non-uniform array
+  assert(b[j][1]==1);
+  assert(b[j][1]==11);
+  assert(b[1][j]==3);
+  assert(b[1][j]==11);
+  assert(b[j][j]==0);
+  assert(b[j][j]==11);
+
+  // Test how we deal with reading off the end of an array
+  assert(a[100][0]==0);
+  assert(a[0][100]==0);
+
+  // Test how we deal with writing off the end of an array
+  int c=0;
+  a[100][0]=1;
+  assert(c==0);
+  c=0;
+  a[0][100]=1;
+  assert(c==0);
+
+  // Test how we deal with merging for an index with one possible value when
+  // writing to an array
+  int ei[3][3]={{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
+  ei[i][1]=1;
+  assert(ei[0][1]==1);
+  assert(ei[0][1]==0);
+  assert(ei[2][1]==0);
+  assert(ei[2][1]==1);
+
+  // Test how we deal with merging for an index with two possible values when
+  // writing to an array
+  int ej[3][3]={{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
+  ej[j][1]=1;
+  assert(ej[0][1]==0);
+  assert(ej[2][1]==0);
+
+  // Test how we deal with merging for an index with two possible values when
+  // it means writing to an array element that may be out of bounds
+  int ek[3][3]={{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
+  c=0;
+  ek[k][1]=1;
+  assert(ek[0][1]==0);
+  assert(c==0);
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c
new file mode 100644
index 00000000000..907fc4180ad
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c
@@ -0,0 +1,156 @@
+#include 
+
+int main(int argc, char *argv[])
+{
+  // Test how well we can represent arrays of pointers
+  int a0=0;
+  int a1=1;
+  int a2=2;
+  int a3=3;
+  int b0=10;
+  int b1=11;
+  int b2=12;
+  int b3=13;
+  int c0=20;
+  int c1=21;
+  int c2=22;
+  int c3=23;
+  int d0=30;
+  int d1=31;
+  int d2=32;
+  int d3=33;
+  // A uniform constant array
+  int *a[3]={&a0, &a0, &a0};
+  // A non-uniform constant array
+  int *b[3]={&b0, &b1, &b2};
+
+  // Test if we can represent uniform constant arrays
+  assert(a[1]==&a0);
+  assert(a[1]==&a3);
+  assert(*a[1]==0);
+  assert(*a[1]==3);
+
+  // Test if we can represent constant arrays which aren't uniform
+  assert(b[1]==&b1);
+  assert(b[1]==&b3);
+  assert(*b[1]==11);
+  assert(*b[1]==13);
+
+  // Test alternative syntax for accessing an array value
+  assert(*(b+1)==&b1);
+  assert(*(b+1)==&b3);
+  assert(*(1+b)==&b1);
+  assert(*(1+b)==&b3);
+  assert(1[b]==&b1);
+  assert(1[b]==&b3);
+  assert(**(b+1)==11);
+  assert(**(b+1)==13);
+  assert(**(1+b)==11);
+  assert(**(1+b)==13);
+  assert(*1[b]==11);
+  assert(*1[b]==13);
+
+  // c and d are arrays whose values requiring merging paths in the CFG. For
+  // c[0] there is only one possibility after merging and for d[0] there are
+  // two.
+  int *c[3]={&c0, &c1, &c2};
+  int *d[3]={&d0, &d1, &d2};
+  if(argc>2)
+  {
+    c[0]=&c3;
+    d[0]=&d3;
+  }
+
+  // Test how well we can deal with merging for an array value
+  assert(c[0]==&c0);
+  assert(c[0]==&c3);
+  assert(d[0]==&d0);
+  assert(d[0]==&d3);
+  assert(*c[0]==20);
+  assert(*c[0]==23);
+  assert(*d[0]==30);
+  assert(*d[0]==33);
+
+  // The variables i, j and k will be used as indexes into arrays of size 3.
+  // They all require merging paths in the CFG. For i there is only one value on
+  // both paths, which is a valid index. The rest can each take two different
+  // values. For j both of these values are valid indexes. For k one is and one
+  // isn't.
+  int i=0;
+  int j=0;
+  int k=0;
+  if(argc>3)
+  {
+    i=0;
+    j=1;
+    k=100;
+  }
+
+  // Test how well we can deal with merging for an index on a uniform array
+  assert(a[i]==&a0);
+  assert(a[i]==&a3);
+  assert(a[j]==&a0);
+  assert(a[j]==&a3);
+  assert(*a[i]==0);
+  assert(*a[i]==3);
+  assert(*a[j]==0);
+  assert(*a[j]==3);
+
+  // Test how well we can deal with merging for an index on a non-uniform array
+  assert(b[i]==&b0);
+  assert(b[i]==&b1);
+  assert(b[j]==&b0);
+  assert(b[j]==&b3);
+  assert(*b[i]==10);
+  assert(*b[i]==11);
+  assert(*b[j]==10);
+  assert(*b[j]==13);
+
+  // Test how we deal with reading off the end of an array
+  assert(a[100]==&a2);
+  assert(*a[100]==2);
+
+  // Test how we deal with writing off the end of an array
+  a[100]=&a2;
+  assert(b[1]==&b1);
+  assert(*b[1]==11);
+
+  // Test how we deal with merging for an index with one possible value when
+  // writing to an array
+  int ei0=40;
+  int ei1=41;
+  int *ei[3]={&ei0, &ei0, &ei0};
+  ei[i]=&ei1;
+  assert(ei[0]==&ei1);
+  assert(ei[0]==&ei0);
+  assert(ei[2]==&ei0);
+  assert(ei[2]==&ei1);
+  assert(*ei[0]==41);
+  assert(*ei[0]==40);
+  assert(*ei[2]==40);
+  assert(*ei[2]==41);
+
+  // Test how we deal with merging for an index with two possible values when
+  // writing to an array
+  int ej0=50;
+  int ej1=51;
+  int *ej[3]={&ej0, &ej0, &ej0};
+  ej[j]=&ej1;
+  assert(ej[0]==&ej0);
+  assert(ej[2]==&ej0);
+  assert(ej[2]==&ej1);
+  assert(*ej[0]==50);
+  assert(*ej[2]==50);
+  assert(*ej[2]==51);
+
+  // Test how we deal with merging for an index with two possible values when
+  // it means writing to an array element that may be out of bounds
+  int ek0=60;
+  int ek1=61;
+  int *ek[3]={&ek0, &ek0, &ek0};
+  ek[k]=&ek1;
+  assert(ek[0]==&ek0);
+  assert(*ek[0]==60);
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/array_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/array_sensitivity_tests.c
new file mode 100644
index 00000000000..68bace194c8
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/array_sensitivity_tests.c
@@ -0,0 +1,101 @@
+#include 
+
+int main(int argc, char *argv[])
+{
+  // A uniform constant array
+  int a[3]={0, 0, 0};
+  // A non-uniform constant array
+  int b[3]={1, 0, 0};
+
+  // Test if we can represent uniform constant arrays
+  assert(a[1]==0);
+  assert(a[1]==1);
+
+  // Test if we can represent constant arrays which aren't uniform
+  assert(b[1]==0);
+  assert(b[1]==1);
+
+  // Test alternative syntax for accessing an array value
+  assert(*(b+1)==0);
+  assert(*(b+1)==1);
+  assert(*(1+b)==0);
+  assert(*(1+b)==1);
+  assert(1[b]==0);
+  assert(1[b]==1);
+
+  // c and d are arrays whose values requiring merging paths in the CFG. For
+  // c[0] there is only one possibility after merging and for d[0] there are
+  // two.
+  int c[3]={0, 0, 0};
+  int d[3]={0, 0, 0};
+  if(argc>2)
+  {
+    c[0]=0;
+    d[0]=1;
+  }
+
+  // Test how well we can deal with merging for an array value
+  assert(c[0]==0);
+  assert(c[0]==1);
+  assert(d[0]==0);
+  assert(d[0]==2);
+  assert(d[1]==0);
+
+  // The variables i, j and k will be used as indexes into arrays of size 3.
+  // They all require merging paths in the CFG. For i there is only one value on
+  // both paths, which is a valid index. The rest can each take two different
+  // values. For j both of these values are valid indexes. For k one is and one
+  // isn't.
+  int i=0;
+  int j=0;
+  int k=0;
+  if(argc>3)
+  {
+    i=0;
+    j=1;
+    k=100;
+  }
+
+  // Test how well we can deal with merging for an index on a uniform array
+  assert(a[i]==0);
+  assert(a[i]==1);
+  assert(a[j]==0);
+  assert(a[j]==1);
+
+  // Test how well we can deal with merging for an index on a non-uniform array
+  assert(b[i]==1);
+  assert(b[i]==0);
+  assert(b[j]==0);
+  assert(b[j]==1);
+
+  // Test how we deal with reading off the end of an array
+  assert(a[100]==0);
+
+  // Test how we deal with writing off the end of an array
+  a[100]=1;
+  assert(b[1]==0);
+
+  // Test how we deal with merging for an index with one possible value when
+  // writing to an array
+  int ei[3]={0, 0, 0};
+  ei[i]=1;
+  assert(ei[0]==1);
+  assert(ei[0]==0);
+  assert(ei[2]==0);
+  assert(ei[2]==1);
+
+  // Test how we deal with merging for an index with two possible values when
+  // writing to an array
+  int ej[3]={0, 0, 0};
+  ej[j]=1;
+  assert(ej[0]==0);
+  assert(ej[2]==0);
+
+  // Test how we deal with merging for an index with two possible values when
+  // it means writing to an array element that may be out of bounds
+  int ek[3]={0, 0, 0};
+  ek[k]=1;
+  assert(ek[0]==0);
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/char_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/char_sensitivity_tests.c
new file mode 100644
index 00000000000..9e87454b68e
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/char_sensitivity_tests.c
@@ -0,0 +1,10 @@
+#include 
+
+int main(int argc, char *argv[])
+{
+  // Test if we can represent constant chars
+  char x='a';
+  assert(x=='a');
+  assert(x=='b');
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/float_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/float_sensitivity_tests.c
new file mode 100644
index 00000000000..1f73fae4a6c
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/float_sensitivity_tests.c
@@ -0,0 +1,10 @@
+#include 
+
+int main(int argc, char *argv[])
+{
+  // Test if we can represent constant floats
+  float x=0.0;
+  assert(x==0.0);
+  assert(x==1.0);
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/int_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/int_sensitivity_tests.c
new file mode 100644
index 00000000000..ab4265a051f
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/int_sensitivity_tests.c
@@ -0,0 +1,55 @@
+#include 
+
+int main(int argc, char *argv[])
+{
+  // Test how well we can represent ints, and also that the transformers are
+  // working correctly.
+  int x=0;
+  int y=0;
+  if(argc>2)
+  {
+    y=1;
+  }
+  assert(x==0);
+  assert(x==1);
+  assert(x==y);
+
+  assert(x<1);
+  assert(x<-1);
+  assert(x-1);
+  assert(x>1);
+  assert(x>y);
+
+  assert(x!=1);
+  assert(x!=0);
+  assert(x!=y);
+
+  assert(!(x==1));
+  assert(!(x==0));
+  assert(!(x==y));
+
+  // Test how well we can represent an int when it has more than one possible
+  // value
+  assert(y<2);
+  assert(y>2);
+  assert(y==1);
+
+  // Try copying a variable and then modifying the original
+  int z=x;
+  x=10;
+  assert(z==0);
+  assert(z==10);
+
+  // Test how we treat assertions in unreachable code
+  x=0;
+  if(0)
+  {
+    assert(x==0);
+    assert(x==1);
+    assert(y==0);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/pointer_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/pointer_sensitivity_tests.c
new file mode 100644
index 00000000000..be328fa4a5d
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/pointer_sensitivity_tests.c
@@ -0,0 +1,53 @@
+#include 
+
+int main(int argc, char *argv[])
+{
+  // Test how well we can represent pointers
+  // Basic use of addresses
+  int a=0;
+  int b=0;
+  int c=0;
+  int *x=&a;
+  int *x2=&a;
+  int *y=&b;
+  assert(x==&a);
+  assert(x==&b);
+  assert(x==x2);
+  assert(x==y);
+
+  // Reading from a dereferenced pointer
+  assert(*x==0);
+  assert(*x==1);
+
+  // Modify the referenced value and access it through the pointer again
+  a=1;
+  assert(*x==1);
+  assert(*x==0);
+
+  // Writing to a dereferenced pointer
+  *x=2;
+  assert(a==2);
+  assert(a==0);
+
+  // Conditionally reassign the pointer, but to the same value
+  if(argc>2)
+  {
+    x=&a;
+  }
+  assert(x==&a);
+
+  // Conditionally reassign the pointer, to a different value this time
+  if(argc>3)
+  {
+    x=&b;
+  }
+  else
+  {
+    x=&c;
+  }
+  assert(*x==0);
+  assert(x==&a);
+  assert(x==&b);
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c
new file mode 100644
index 00000000000..db9fe720e15
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c
@@ -0,0 +1,59 @@
+#include 
+#include 
+
+int main(int argc, char *argv[])
+{
+  // Test reading from an array using a pointer
+  int a[3]={1, 2, 3};
+  int *p=a;
+  assert(p==&a[0]);
+  assert(*p==1);
+
+  // Test pointer arithmetic
+  int *q=&a[1];
+  assert(q==p+1);
+  assert(*q==2);
+
+  // Test pointer diffs
+  ptrdiff_t x=1;
+  assert(q-p==x);
+
+  // Test writing into an array using a pointer
+  *q=4;
+  assert(a[1]==4);
+  a[1]=2;
+
+  // We now explore pointers and indexes each with more than one possible value
+  int *r=&a[1];
+  int b[3]={0, 0, 0};
+  int *s=&b[1];
+  int i=1;
+  if (argc>2)
+  {
+    r=&a[2];
+    s=&b[2];
+    i=2;
+  }
+
+  // Test reading from an array using a pointer with more than one possible
+  // value
+  assert(*r==2);
+  assert(*r==1);
+  assert(*s==0);
+  assert(*s==1);
+
+  // Test pointer arithmetic with an unknown index
+  int *t=&a[i];
+  assert(t==p+i);
+
+  // Test pointer diffs with an unknown index
+  ptrdiff_t y=i;
+  assert(t-p==y);
+
+  // Test writing into an array using a pointer with an unknown index
+  *r=5;
+  assert(a[i]==5);
+  assert(a[1]==5);
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_pointer_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_pointer_sensitivity_tests.c
new file mode 100644
index 00000000000..ee29a7059db
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_pointer_sensitivity_tests.c
@@ -0,0 +1,24 @@
+#include 
+
+int main(int argc, char *argv[])
+{
+  // Test how well we can represent pointers to pointers
+  // Basic use of addresses
+  int a=0;
+  int *p=&a;
+  int **x=&p;
+
+  // Reading from a pointer to a pointer that's been dereferenced twice
+  assert(**x==0);
+  assert(**x==1);
+  a=1;
+  assert(**x==1);
+  assert(**x==0);
+
+  // Writing to a pointer to a pointer that's been dereferenced twice
+  **x=2;
+  assert(a==2);
+  assert(a==1);
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_struct_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_struct_sensitivity_tests.c
new file mode 100644
index 00000000000..e0092afae4a
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/pointer_to_struct_sensitivity_tests.c
@@ -0,0 +1,28 @@
+#include 
+
+int main(int argc, char *argv[])
+{
+  // Test how well we can represent pointers to structs
+  struct int_float
+  {
+	int a;
+	float b;
+  };
+  struct int_float x={0, 1.0};
+  x.a=0;
+  x.b=1.0;
+  struct int_float *p=&x;
+  assert((*p).a==0);
+  assert((*p).a==1);
+
+  // Test alternative syntax
+  assert(p->a==0);
+  assert(p->a==1);
+
+  // Test writing to the struct through the pointer
+  p->b=2.0;
+  assert(p->b==2.0);
+  assert(p->b==1.0);
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/struct_of_array_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/struct_of_array_sensitivity_tests.c
new file mode 100644
index 00000000000..d5924b71ed7
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/struct_of_array_sensitivity_tests.c
@@ -0,0 +1,58 @@
+#include 
+
+int main(int argc, char *argv[])
+{
+  // Test how well we can represent structs
+  struct int_array_float_array
+  {
+	int a[3];
+	float b[3];
+  };
+  struct int_array_float_array x={{0, 1, 2}, {3.0f, 4.0f, 5.0f}};
+  x.a[0]=0;
+  x.a[1]=1;
+  x.a[2]=2;
+  x.b[0]=3.0f;
+  x.b[1]=4.0f;
+  x.b[2]=5.0f;
+  assert(x.a[0]==0);
+  assert(*(x.a+0)==0);
+  assert(*(0+x.a)==0);
+  assert(0[x.a]==0);
+
+  // Test merging when there is only one value on both paths
+  if(argc>2)
+  {
+    x.a[0]=0;
+  }
+  assert(x.a[0]==0);
+  assert(x.a[1]==1);
+  assert(x.b[0]==3.0f);
+
+  // Test merging when there is one value for a and two values for b, to test if
+  // we are representing them separately
+  if(argc>3)
+  {
+    x.a[0]=0;
+    x.b[2]=15.0f;
+  }
+  assert(x.a[0]==0);
+  assert(x.a[1]==1);
+  assert(x.b[2]>0.0f);
+  assert(x.b[2]==15.0f);
+  assert(x.b[2]==1.0f);
+  assert(x.b[0]==3.0f);
+
+  // Test merging when there are two values for a and b
+  if(argc>4)
+  {
+    x.a[0]=11;
+    x.b[2]=25.0f;
+  }
+  assert(x.a[0]<12);
+  assert(x.a[0]>2);
+  assert(x.a[0]==0);
+  assert(x.a[1]==1);
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/struct_of_pointer_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/struct_of_pointer_sensitivity_tests.c
new file mode 100644
index 00000000000..3cde8011c2b
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/struct_of_pointer_sensitivity_tests.c
@@ -0,0 +1,71 @@
+#include 
+
+int main(int argc, char *argv[])
+{
+  // Test how well we can represent structs of pointers
+  int a1=0;
+  int a2=1;
+  int a3=2;
+  float b1=10.0f;
+  float b2=11.0f;
+  float b3=12.0f;
+  float b4=13.0f;
+  struct int_float
+  {
+    int *a;
+    float *b;
+  };
+  struct int_float x;
+  x.a=&a1;
+  x.b=&b1;
+  assert(x.a==&a1);
+  assert(x.a==&a2);
+  assert(x.b==&b1);
+  assert(x.b==&b2);
+  assert(*x.a==0);
+  assert(*x.a==100);
+  assert(*x.b==10.0f);
+  assert(*x.b==110.0f);
+
+  // Test merging when there is only one value on both paths
+  if(argc>2)
+  {
+    x.a=&a1;
+    x.b=&b1;
+  }
+  assert(x.a==&a1);
+  assert(x.a==&a2);
+  assert(*x.a==0);
+  assert(*x.a==100);
+
+  // Test merging when there is one value for a and two values for b, to test if
+  // we are representing them separately
+  if(argc>3)
+  {
+    x.a=&a1;
+    x.b=&b2;
+  }
+  assert(x.a==&a1);
+  assert(x.b==&b2);
+  assert(x.b==&b3);
+  assert(*x.a==0);
+  assert(*x.b==11.0f);
+  assert(*x.b==12.0f);
+
+  // Test merging when there are two values for a and b
+  if(argc>4)
+  {
+    x.a=&a2;
+    x.b=&b3;
+  }
+  assert(x.a==&a2);
+  assert(x.a==&a3);
+  assert(x.b==&b3);
+  assert(x.b==&b4);
+  assert(*x.a==1);
+  assert(*x.a==2);
+  assert(*x.b==12.0f);
+  assert(*x.b==13.0f);
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/struct_of_struct_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/struct_of_struct_sensitivity_tests.c
new file mode 100644
index 00000000000..ac6a32a0086
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/struct_of_struct_sensitivity_tests.c
@@ -0,0 +1,55 @@
+#include 
+
+int main(int argc, char *argv[])
+{
+  // Test how well we can represent structs of structs
+  struct int_float
+  {
+    int a;
+    float b;
+  };
+  struct two_int_floats
+  {
+    struct int_float s1;
+    struct int_float s2;
+  };
+  struct two_int_floats x;
+  x.s1.a=0;
+  x.s1.b=1.0;
+  x.s2.a=2;
+  x.s2.b=3.0f;
+  assert(x.s1.a==0);
+  assert(x.s2.b==3.0f);
+
+  // Test merging when there is only one value on both paths
+  if(argc>2)
+  {
+    x.s1.a=0;
+  }
+  assert(x.s1.a==0);
+  assert(x.s1.a==10);
+
+  // Test merging when there is one value for s1 and two values for s2, to test
+  // if we are representing them separately
+  if(argc>3)
+  {
+    x.s1.b=1.0f;
+    x.s2.b=13.0f;
+  }
+  assert(x.s1.b==1.0f);
+  assert(x.s2.b==3.0f);
+  assert(x.s2.b==0.0f);
+
+  // Test merging when there are two values for s1 and s2
+  if(argc>4)
+  {
+    x.s1.a=20;
+    x.s2.a=22;
+  }
+  assert(x.s1.a==20);
+  assert(x.s1.a<30);
+  assert(x.s2.a==22);
+  assert(x.s2.a<30);
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-common-files/struct_sensitivity_tests.c b/regression/goto-analyzer/sensitivity-test-common-files/struct_sensitivity_tests.c
new file mode 100644
index 00000000000..a4ad229e34c
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-common-files/struct_sensitivity_tests.c
@@ -0,0 +1,47 @@
+#include 
+
+int main(int argc, char *argv[])
+{
+  // Test how well we can represent structs
+  struct int_float
+  {
+	int a;
+	float b;
+  };
+  struct int_float x={0, 1.0f};
+  x.a=0;
+  x.b=1.0f;
+  assert(x.a==0);
+  assert(x.a==1);
+
+  // Test merging when there is only one value on both paths
+  if(argc>2)
+  {
+    x.a=0;
+    x.b=1.0f;
+  }
+  assert(x.a==0);
+
+  // Test merging when there is one value for a and two values for b, to test if
+  // we are representing them separately
+  if(argc>3)
+  {
+    x.a=0;
+    x.b=2.0f;
+  }
+  assert(x.a==0);
+  assert(x.b>0.0f);
+  assert(x.b==1.0f);
+
+  // Test merging when there are two values for a and b
+  if(argc>4)
+  {
+    x.a=1;
+    x.b=2.0f;
+  }
+  assert(x.a<2);
+  assert(x.a>2);
+  assert(x.a==1);
+
+  return 0;
+}
diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/sensitivity_test_constants_array_of_constants_array.c b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/sensitivity_test_constants_array_of_constants_array.c
new file mode 100644
index 00000000000..103849f7a32
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/sensitivity_test_constants_array_of_constants_array.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/array_of_array_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/test.desc
new file mode 100644
index 00000000000..c8db44a2c09
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-array/test.desc
@@ -0,0 +1,73 @@
+FUTURE
+sensitivity_test_constants_array_of_constants_array.c
+--variable --arrays --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion a\[1\]\[2\]==0: Success$
+^\[main.assertion.2\] .* assertion a\[1\]\[2\]==1: Failure \(if reachable\)$
+^\[main.assertion.3\] .* assertion b\[1\]\[2\]==5: Success$
+^\[main.assertion.4\] .* assertion b\[1\]\[2\]==0: Failure \(if reachable\)$
+^\[main.assertion.5\] .* assertion \*\(b\[1\]\+2\)==5: Success$
+^\[main.assertion.6\] .* assertion \*\(b\[1\]\+2\)==0: Failure \(if reachable\)$
+^\[main.assertion.7\] .* assertion \(\*\(b\+1\)\)\[2\]==5: Success$
+^\[main.assertion.8\] .* assertion \(\*\(b\+1\)\)\[2\]==0: Failure \(if reachable\)$
+^\[main.assertion.9\] .* assertion \*\(\*\(b\+1\)\+2\)==5: Success$
+^\[main.assertion.10\] .* assertion \*\(\*\(b\+1\)\+2\)==0: Failure \(if reachable\)$
+^\[main.assertion.11\] .* assertion 1\[b\]\[2\]==5: Success$
+^\[main.assertion.12\] .* assertion 1\[b\]\[2\]==0: Failure \(if reachable\)$
+^\[main.assertion.13\] .* assertion \*\(1\[b\]\+2\)==5: Success$
+^\[main.assertion.14\] .* assertion \*\(1\[b\]\+2\)==0: Failure \(if reachable\)$
+^\[main.assertion.15\] .* assertion \(\*\(1\+b\)\)\[2\]==5: Unknown$
+^\[main.assertion.16\] .* assertion \(\*\(1\+b\)\)\[2\]==0: Unknown$
+^\[main.assertion.17\] .* assertion \*\(\*\(1\+b\)\+2\)==5: Unknown$
+^\[main.assertion.18\] .* assertion \*\(\*\(1\+b\)\+2\)==0: Unknown$
+^\[main.assertion.19\] .* assertion 2\[1\[b\]\]==5: Success$
+^\[main.assertion.20\] .* assertion 2\[1\[b\]\]==0: Failure \(if reachable\)$
+^\[main.assertion.21\] .* assertion \*\(2\+1\[b\]\)==5: Unknown$
+^\[main.assertion.22\] .* assertion \*\(2\+1\[b\]\)==0: Unknown$
+^\[main.assertion.23\] .* assertion \*\(2\+\*\(1\+b\)\)==5: Unknown$
+^\[main.assertion.24\] .* assertion \*\(2\+\*\(1\+b\)\)==0: Unknown$
+^\[main.assertion.25\] .* assertion a\[0\]\[1\]==0: Success$
+^\[main.assertion.26\] .* assertion a\[0\]\[1\]==1: Failure \(if reachable\)$
+^\[main.assertion.27\] .* assertion a\[0\]\[2\]==0: Success$
+^\[main.assertion.28\] .* assertion b\[0\]\[1\]==2: Unknown$
+^\[main.assertion.29\] .* assertion b\[0\]\[1\]==3: Unknown$
+^\[main.assertion.30\] .* assertion b\[0\]\[2\]==2: Success$
+^\[main.assertion.31\] .* assertion a\[i\]\[1\]==0: Success$
+^\[main.assertion.32\] .* assertion a\[i\]\[1\]==1: Failure \(if reachable\)$
+^\[main.assertion.33\] .* assertion a\[1\]\[i\]==0: Success$
+^\[main.assertion.34\] .* assertion a\[1\]\[i\]==1: Failure \(if reachable\)$
+^\[main.assertion.35\] .* assertion a\[i\]\[i\]==0: Success$
+^\[main.assertion.36\] .* assertion a\[i\]\[i\]==1: Failure \(if reachable\)$
+^\[main.assertion.37\] .* assertion a\[j\]\[1\]==0: Unknown$
+^\[main.assertion.38\] .* assertion a\[j\]\[1\]==1: Unknown$
+^\[main.assertion.39\] .* assertion a\[1\]\[j\]==0: Unknown$
+^\[main.assertion.40\] .* assertion a\[1\]\[j\]==1: Unknown$
+^\[main.assertion.41\] .* assertion a\[j\]\[j\]==0: Unknown$
+^\[main.assertion.42\] .* assertion a\[j\]\[j\]==1: Unknown$
+^\[main.assertion.43\] .* assertion b\[i\]\[1\]==1: Success$
+^\[main.assertion.44\] .* assertion b\[i\]\[1\]==11: Failure \(if reachable\)$
+^\[main.assertion.45\] .* assertion b\[1\]\[i\]==3: Success$
+^\[main.assertion.46\] .* assertion b\[1\]\[i\]==11: Failure \(if reachable\)$
+^\[main.assertion.47\] .* assertion b\[i\]\[i\]==0: Success$
+^\[main.assertion.48\] .* assertion b\[i\]\[i\]==11: Failure \(if reachable\)$
+^\[main.assertion.49\] .* assertion b\[j\]\[1\]==1: Unknown$
+^\[main.assertion.50\] .* assertion b\[j\]\[1\]==11: Unknown$
+^\[main.assertion.51\] .* assertion b\[1\]\[j\]==3: Unknown$
+^\[main.assertion.52\] .* assertion b\[1\]\[j\]==11: Unknown$
+^\[main.assertion.53\] .* assertion b\[j\]\[j\]==0: Unknown$
+^\[main.assertion.54\] .* assertion b\[j\]\[j\]==11: Unknown$
+^\[main.assertion.55\] .* assertion a\[100\]\[0\]==0: Unknown$
+^\[main.assertion.56\] .* assertion a\[0\]\[100\]==0: Unknown$
+^\[main.assertion.57\] .* assertion c==0: Success$
+^\[main.assertion.58\] .* assertion c==0: Success$
+^\[main.assertion.59\] .* assertion ei\[0\]\[1\]==1: Success$
+^\[main.assertion.60\] .* assertion ei\[0\]\[1\]==0: Failure \(if reachable\)$
+^\[main.assertion.61\] .* assertion ei\[2\]\[1\]==0: Success$
+^\[main.assertion.62\] .* assertion ei\[2\]\[1\]==1: Failure \(if reachable\)$
+^\[main.assertion.63\] .* assertion ej\[0\]\[1\]==0: Unknown$
+^\[main.assertion.64\] .* assertion ej\[2\]\[1\]==0: Unknown$
+^\[main.assertion.65\] .* assertion ek\[0\]\[1\]==0: Unknown$
+^\[main.assertion.66\] .* assertion c==0: Success$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/sensitivity_test_constants_array_of_constants_pointer.c b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/sensitivity_test_constants_array_of_constants_pointer.c
new file mode 100644
index 00000000000..66edcccfbfb
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/sensitivity_test_constants_array_of_constants_pointer.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc
new file mode 100644
index 00000000000..9242552c707
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-constants-pointer/test.desc
@@ -0,0 +1,71 @@
+FUTURE
+sensitivity_test_constants_array_of_constants_pointer.c
+--variable --arrays --pointers --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion a\[1\]==&a0: Success$
+^\[main.assertion.2\] .* assertion a\[1\]==&a3: Failure \(if reachable\)$
+^\[main.assertion.3\] .* assertion \*a\[1\]==0: Success$
+^\[main.assertion.4\] .* assertion \*a\[1\]==3: Failure \(if reachable\)$
+^\[main.assertion.5\] .* assertion b\[1\]==&b1: Success$
+^\[main.assertion.6\] .* assertion b\[1\]==&b3: Failure \(if reachable\)$
+^\[main.assertion.7\] .* assertion \*b\[1\]==11: Success$
+^\[main.assertion.8\] .* assertion \*b\[1\]==13: Failure \(if reachable\)$
+^\[main.assertion.9\] .* assertion \*\(b\+1\)==&b1: Success$
+^\[main.assertion.10\] .* assertion \*\(b\+1\)==&b3: Failure \(if reachable\)$
+^\[main.assertion.11\] .* assertion \*\(1\+b\)==&b1: Unknown$
+^\[main.assertion.12\] .* assertion \*\(1\+b\)==&b3: Unknown$
+^\[main.assertion.13\] .* assertion 1\[b\]==&b1: Success$
+^\[main.assertion.14\] .* assertion 1\[b\]==&b3: Failure \(if reachable\)$
+^\[main.assertion.15\] .* assertion \*\*\(b\+1\)==11: Success$
+^\[main.assertion.16\] .* assertion \*\*\(b\+1\)==13: Failure \(if reachable\)$
+^\[main.assertion.17\] .* assertion \*\*\(1\+b\)==11: Unknown$
+^\[main.assertion.18\] .* assertion \*\*\(1\+b\)==13: Unknown$
+^\[main.assertion.19\] .* assertion \*1\[b\]==11: Success$
+^\[main.assertion.20\] .* assertion \*1\[b\]==13: Failure \(if reachable\)$
+^\[main.assertion.21\] .* assertion c\[0\]==&c0: Unknown$
+^\[main.assertion.22\] .* assertion c\[0\]==&c3: Unknown$
+^\[main.assertion.23\] .* assertion d\[0\]==&d0: Unknown$
+^\[main.assertion.24\] .* assertion d\[0\]==&d3: Unknown$
+^\[main.assertion.25\] .* assertion \*c\[0\]==20: Unknown$
+^\[main.assertion.26\] .* assertion \*c\[0\]==23: Unknown$
+^\[main.assertion.27\] .* assertion \*d\[0\]==30: Unknown$
+^\[main.assertion.28\] .* assertion \*d\[0\]==33: Unknown$
+^\[main.assertion.29\] .* assertion a\[i\]==&a0: Success$
+^\[main.assertion.30\] .* assertion a\[i\]==&a3: Failure \(if reachable\)$
+^\[main.assertion.31\] .* assertion a\[j\]==&a0: Unknown$
+^\[main.assertion.32\] .* assertion a\[j\]==&a3: Unknown$
+^\[main.assertion.33\] .* assertion \*a\[i\]==0: Success$
+^\[main.assertion.34\] .* assertion \*a\[i\]==3: Failure \(if reachable\)$
+^\[main.assertion.35\] .* assertion \*a\[j\]==0: Unknown$
+^\[main.assertion.36\] .* assertion \*a\[j\]==3: Unknown$
+^\[main.assertion.37\] .* assertion b\[i\]==&b0: Success$
+^\[main.assertion.38\] .* assertion b\[i\]==&b1: Failure \(if reachable\)$
+^\[main.assertion.39\] .* assertion b\[j\]==&b0: Unknown$
+^\[main.assertion.40\] .* assertion b\[j\]==&b3: Unknown$
+^\[main.assertion.41\] .* assertion \*b\[i\]==10: Success$
+^\[main.assertion.42\] .* assertion \*b\[i\]==11: Failure \(if reachable\)$
+^\[main.assertion.43\] .* assertion \*b\[j\]==10: Unknown$
+^\[main.assertion.44\] .* assertion \*b\[j\]==13: Unknown$
+^\[main.assertion.45\] .* assertion a\[100\]==&a2: Unknown$
+^\[main.assertion.46\] .* assertion \*a\[100\]==2: Unknown$
+^\[main.assertion.47\] .* assertion b\[1\]==&b1: Success$
+^\[main.assertion.48\] .* assertion \*b\[1\]==11: Success$
+^\[main.assertion.49\] .* assertion ei\[0\]==&ei1: Success$
+^\[main.assertion.50\] .* assertion ei\[0\]==&ei0: Failure \(if reachable\)$
+^\[main.assertion.51\] .* assertion ei\[2\]==&ei0: Success$
+^\[main.assertion.52\] .* assertion ei\[2\]==&ei1: Failure \(if reachable\)$
+^\[main.assertion.53\] .* assertion \*ei\[0\]==41: Success$
+^\[main.assertion.54\] .* assertion \*ei\[0\]==40: Failure \(if reachable\)$
+^\[main.assertion.55\] .* assertion \*ei\[2\]==40: Success$
+^\[main.assertion.56\] .* assertion \*ei\[2\]==41: Failure \(if reachable\)$
+^\[main.assertion.57\] .* assertion ej\[0\]==&ej0: Unknown$
+^\[main.assertion.58\] .* assertion ej\[2\]==&ej0: Unknown$
+^\[main.assertion.59\] .* assertion ej\[2\]==&ej1: Unknown$
+^\[main.assertion.60\] .* assertion \*ej\[0\]==50: Unknown$
+^\[main.assertion.61\] .* assertion \*ej\[2\]==50: Unknown$
+^\[main.assertion.62\] .* assertion \*ej\[2\]==51: Unknown$
+^\[main.assertion.63\] .* assertion ek\[0\]==&ek0: Unknown$
+^\[main.assertion.64\] .* assertion \*ek\[0\]==60: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/sensitivity_test_constants_array_of_two_value_pointer.c b/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/sensitivity_test_constants_array_of_two_value_pointer.c
new file mode 100644
index 00000000000..66edcccfbfb
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/sensitivity_test_constants_array_of_two_value_pointer.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc
new file mode 100644
index 00000000000..74f5f128ed6
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-array-of-two-value-pointer/test.desc
@@ -0,0 +1,71 @@
+FUTURE
+sensitivity_test_constants_array_of_two_value_pointer.c
+--variable --arrays --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion a\[1\]==&a0: Unknown$
+^\[main.assertion.2\] .* assertion a\[1\]==&a3: Unknown$
+^\[main.assertion.3\] .* assertion \*a\[1\]==0: Unknown$
+^\[main.assertion.4\] .* assertion \*a\[1\]==3: Unknown$
+^\[main.assertion.5\] .* assertion b\[1\]==&b1: Unknown$
+^\[main.assertion.6\] .* assertion b\[1\]==&b3: Unknown$
+^\[main.assertion.7\] .* assertion \*b\[1\]==11: Unknown$
+^\[main.assertion.8\] .* assertion \*b\[1\]==13: Unknown$
+^\[main.assertion.9\] .* assertion \*\(b\+1\)==&b1: Unknown$
+^\[main.assertion.10\] .* assertion \*\(b\+1\)==&b3: Unknown$
+^\[main.assertion.11\] .* assertion \*\(1\+b\)==&b1: Unknown$
+^\[main.assertion.12\] .* assertion \*\(1\+b\)==&b3: Unknown$
+^\[main.assertion.13\] .* assertion 1\[b\]==&b1: Unknown$
+^\[main.assertion.14\] .* assertion 1\[b\]==&b3: Unknown$
+^\[main.assertion.15\] .* assertion \*\*\(b\+1\)==11: Unknown$
+^\[main.assertion.16\] .* assertion \*\*\(b\+1\)==13: Unknown$
+^\[main.assertion.17\] .* assertion \*\*\(1\+b\)==11: Unknown$
+^\[main.assertion.18\] .* assertion \*\*\(1\+b\)==13: Unknown$
+^\[main.assertion.19\] .* assertion \*1\[b\]==11: Unknown$
+^\[main.assertion.20\] .* assertion \*1\[b\]==13: Unknown$
+^\[main.assertion.21\] .* assertion c\[0\]==&c0: Unknown$
+^\[main.assertion.22\] .* assertion c\[0\]==&c3: Unknown$
+^\[main.assertion.23\] .* assertion d\[0\]==&d0: Unknown$
+^\[main.assertion.24\] .* assertion d\[0\]==&d3: Unknown$
+^\[main.assertion.25\] .* assertion \*c\[0\]==20: Unknown$
+^\[main.assertion.26\] .* assertion \*c\[0\]==23: Unknown$
+^\[main.assertion.27\] .* assertion \*d\[0\]==30: Unknown$
+^\[main.assertion.28\] .* assertion \*d\[0\]==33: Unknown$
+^\[main.assertion.29\] .* assertion a\[i\]==&a0: Unknown$
+^\[main.assertion.30\] .* assertion a\[i\]==&a3: Unknown$
+^\[main.assertion.31\] .* assertion a\[j\]==&a0: Unknown$
+^\[main.assertion.32\] .* assertion a\[j\]==&a3: Unknown$
+^\[main.assertion.33\] .* assertion \*a\[i\]==0: Unknown$
+^\[main.assertion.34\] .* assertion \*a\[i\]==3: Unknown$
+^\[main.assertion.35\] .* assertion \*a\[j\]==0: Unknown$
+^\[main.assertion.36\] .* assertion \*a\[j\]==3: Unknown$
+^\[main.assertion.37\] .* assertion b\[i\]==&b0: Unknown$
+^\[main.assertion.38\] .* assertion b\[i\]==&b1: Unknown$
+^\[main.assertion.39\] .* assertion b\[j\]==&b0: Unknown$
+^\[main.assertion.40\] .* assertion b\[j\]==&b3: Unknown$
+^\[main.assertion.41\] .* assertion \*b\[i\]==10: Unknown$
+^\[main.assertion.42\] .* assertion \*b\[i\]==11: Unknown$
+^\[main.assertion.43\] .* assertion \*b\[j\]==10: Unknown$
+^\[main.assertion.44\] .* assertion \*b\[j\]==13: Unknown$
+^\[main.assertion.45\] .* assertion a\[100\]==&a2: Unknown$
+^\[main.assertion.46\] .* assertion \*a\[100\]==2: Unknown$
+^\[main.assertion.47\] .* assertion b\[1\]==&b1: Unknown$
+^\[main.assertion.48\] .* assertion \*b\[1\]==11: Unknown$
+^\[main.assertion.49\] .* assertion ei\[0\]==&ei1: Unknown$
+^\[main.assertion.50\] .* assertion ei\[0\]==&ei0: Unknown$
+^\[main.assertion.51\] .* assertion ei\[2\]==&ei0: Unknown$
+^\[main.assertion.52\] .* assertion ei\[2\]==&ei1: Unknown$
+^\[main.assertion.53\] .* assertion \*ei\[0\]==41: Unknown$
+^\[main.assertion.54\] .* assertion \*ei\[0\]==40: Unknown$
+^\[main.assertion.55\] .* assertion \*ei\[2\]==40: Unknown$
+^\[main.assertion.56\] .* assertion \*ei\[2\]==41: Unknown$
+^\[main.assertion.57\] .* assertion ej\[0\]==&ej0: Unknown$
+^\[main.assertion.58\] .* assertion ej\[2\]==&ej0: Unknown$
+^\[main.assertion.59\] .* assertion ej\[2\]==&ej1: Unknown$
+^\[main.assertion.60\] .* assertion \*ej\[0\]==50: Unknown$
+^\[main.assertion.61\] .* assertion \*ej\[2\]==50: Unknown$
+^\[main.assertion.62\] .* assertion \*ej\[2\]==51: Unknown$
+^\[main.assertion.63\] .* assertion ek\[0\]==&ek0: Unknown$
+^\[main.assertion.64\] .* assertion \*ek\[0\]==60: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-array/sensitivity_test_constants_array.c b/regression/goto-analyzer/sensitivity-test-constants-array/sensitivity_test_constants_array.c
new file mode 100644
index 00000000000..e0a5a37a2a2
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-array/sensitivity_test_constants_array.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/array_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-array/test.desc
new file mode 100644
index 00000000000..b48a2c823ca
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-array/test.desc
@@ -0,0 +1,39 @@
+FUTURE
+sensitivity_test_constants_array.c
+--variable --arrays --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion a\[1\]==0: Success$
+^\[main.assertion.2\] .* assertion a\[1\]==1: Failure \(if reachable\)$
+^\[main.assertion.3\] .* assertion b\[1\]==0: Success$
+^\[main.assertion.4\] .* assertion b\[1\]==1: Failure \(if reachable\)$
+^\[main.assertion.5\] .* assertion \*\(b\+1\)==0: Success$
+^\[main.assertion.6\] .* assertion \*\(b\+1\)==1: Failure \(if reachable\)$
+^\[main.assertion.7\] .* assertion \*\(1\+b\)==0: Unknown$
+^\[main.assertion.8\] .* assertion \*\(1\+b\)==1: Unknown$
+^\[main.assertion.9\] .* assertion 1\[b\]==0: Success$
+^\[main.assertion.10\] .* assertion 1\[b\]==1: Failure \(if reachable\)$
+^\[main.assertion.11\] .* assertion c\[0\]==0: Success$
+^\[main.assertion.12\] .* assertion c\[0\]==1: Failure \(if reachable\)$
+^\[main.assertion.13\] .* assertion d\[0\]==0: Unknown$
+^\[main.assertion.14\] .* assertion d\[0\]==2: Unknown$
+^\[main.assertion.15\] .* assertion d\[1\]==0: Success$
+^\[main.assertion.16\] .* assertion a\[i\]==0: Success$
+^\[main.assertion.17\] .* assertion a\[i\]==1: Failure \(if reachable\)$
+^\[main.assertion.18\] .* assertion a\[j\]==0: Unknown$
+^\[main.assertion.19\] .* assertion a\[j\]==1: Unknown$
+^\[main.assertion.20\] .* assertion b\[i\]==1: Success$
+^\[main.assertion.21\] .* assertion b\[i\]==0: Failure \(if reachable\)$
+^\[main.assertion.22\] .* assertion b\[j\]==0: Unknown$
+^\[main.assertion.23\] .* assertion b\[j\]==1: Unknown$
+^\[main.assertion.24\] .* assertion a\[100\]==0: Unknown$
+^\[main.assertion.25\] .* assertion b\[1\]==0: Success$
+^\[main.assertion.26\] .* assertion ei\[0\]==1: Success$
+^\[main.assertion.27\] .* assertion ei\[0\]==0: Failure \(if reachable\)$
+^\[main.assertion.28\] .* assertion ei\[2\]==0: Success$
+^\[main.assertion.29\] .* assertion ei\[2\]==1: Failure \(if reachable\)$
+^\[main.assertion.30\] .* assertion ej\[0\]==0: Unknown$
+^\[main.assertion.31\] .* assertion ej\[2\]==0: Unknown$
+^\[main.assertion.32\] .* assertion ek\[0\]==0: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-char/sensitivity_test_constants_char.c b/regression/goto-analyzer/sensitivity-test-constants-char/sensitivity_test_constants_char.c
new file mode 100644
index 00000000000..b97be63e211
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-char/sensitivity_test_constants_char.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/char_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-char/test.desc b/regression/goto-analyzer/sensitivity-test-constants-char/test.desc
new file mode 100644
index 00000000000..4ae7832010b
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-char/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+sensitivity_test_constants_char.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x=='a': Success$
+^\[main.assertion.2\] .* assertion x=='b': Failure \(if reachable\)$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-float/sensitivity_test_constants_float.c b/regression/goto-analyzer/sensitivity-test-constants-float/sensitivity_test_constants_float.c
new file mode 100644
index 00000000000..4e801235552
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-float/sensitivity_test_constants_float.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/float_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-float/test.desc b/regression/goto-analyzer/sensitivity-test-constants-float/test.desc
new file mode 100644
index 00000000000..634ea862f56
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-float/test.desc
@@ -0,0 +1,9 @@
+FUTURE
+sensitivity_test_constants_float.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x==0.0: Success$
+^\[main.assertion.2\] .* assertion x==1.0: Failure \(if reachable\)$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-int/sensitivity_test_constants_int.c b/regression/goto-analyzer/sensitivity-test-constants-int/sensitivity_test_constants_int.c
new file mode 100644
index 00000000000..8a0f75feb97
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-int/sensitivity_test_constants_int.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/int_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-int/test.desc b/regression/goto-analyzer/sensitivity-test-constants-int/test.desc
new file mode 100644
index 00000000000..d3c274a9447
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-int/test.desc
@@ -0,0 +1,30 @@
+FUTURE
+sensitivity_test_constants_int.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x==0: Success$
+^\[main.assertion.2\] .* assertion x==1: Failure \(if reachable\)$
+^\[main.assertion.3\] .* assertion x==y: Unknown$
+^\[main.assertion.4\] .* assertion x<1: Success$
+^\[main.assertion.5\] .* assertion x<-1: Failure \(if reachable\)$
+^\[main.assertion.6\] .* assertion x-1: Success$
+^\[main.assertion.8\] .* assertion x>1: Failure \(if reachable\)$
+^\[main.assertion.9\] .* assertion x>y: Unknown$
+^\[main.assertion.10\] .* assertion x!=1: Success$
+^\[main.assertion.11\] .* assertion x!=0: Failure \(if reachable\)$
+^\[main.assertion.12\] .* assertion x!=y: Unknown$
+^\[main.assertion.13\] .* assertion !\(x==1\): Success$
+^\[main.assertion.14\] .* assertion !\(x==0\): Failure \(if reachable\)$
+^\[main.assertion.15\] .* assertion !\(x==y\): Unknown$
+^\[main.assertion.16\] .* assertion y<2: Unknown$
+^\[main.assertion.17\] .* assertion y>2: Unknown$
+^\[main.assertion.18\] .* assertion y==1: Unknown$
+^\[main.assertion.19\] .* assertion z==0: Success$
+^\[main.assertion.20\] .* assertion z==10: Failure \(if reachable\)$
+^\[main.assertion.21\] .* assertion x==0: Success \(unreachable\)$
+^\[main.assertion.22\] .* assertion x==1: Success \(unreachable\)$
+^\[main.assertion.23\] .* assertion y==0: Success \(unreachable\)$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/sensitivity_test_constants_pointer_to_constants_array.c b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/sensitivity_test_constants_pointer_to_constants_array.c
new file mode 100644
index 00000000000..082fe2e62c8
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/sensitivity_test_constants_pointer_to_constants_array.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc
new file mode 100644
index 00000000000..7ccb164ab0f
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-array/test.desc
@@ -0,0 +1,21 @@
+FUTURE
+sensitivity_test_constants_pointer_to_constants_array.c
+--variable --pointers --arrays --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion p==&a\[0\]: Success$
+^\[main.assertion.2\] .* assertion \*p==1: Success$
+^\[main.assertion.3\] .* assertion q==p\+1: Unknown$
+^\[main.assertion.4\] .* assertion \*q==2: Unknown$
+^\[main.assertion.5\] .* assertion q-p==x: Unknown$
+^\[main.assertion.6\] .* assertion a\[1\]==4: Unknown$
+^\[main.assertion.7\] .* assertion \*r==2: Unknown$
+^\[main.assertion.8\] .* assertion \*r==1: Unknown$
+^\[main.assertion.9\] .* assertion \*s==0: Unknown$
+^\[main.assertion.10\] .* assertion \*s==1: Unknown$
+^\[main.assertion.11\] .* assertion t==p\+i: Unknown$
+^\[main.assertion.12\] .* assertion t-p==y: Unknown$
+^\[main.assertion.13\] .* assertion a\[i\]==5: Unknown$
+^\[main.assertion.14\] .* assertion a\[1\]==5: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/sensitivity_test_constants_pointer_to_constants_pointer.c b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/sensitivity_test_constants_pointer_to_constants_pointer.c
new file mode 100644
index 00000000000..56e6edc1093
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/sensitivity_test_constants_pointer_to_constants_pointer.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/pointer_to_pointer_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/test.desc
new file mode 100644
index 00000000000..f7fa1706d6a
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-pointer/test.desc
@@ -0,0 +1,13 @@
+FUTURE
+sensitivity_test_constants_pointer_to_constants_pointer.c
+--variable --pointers --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion \*\*x==0: Success$
+^\[main.assertion.2\] .* assertion \*\*x==1: Failure \(if reachable\)$
+^\[main.assertion.3\] .* assertion \*\*x==1: Success$
+^\[main.assertion.4\] .* assertion \*\*x==0: Failure \(if reachable\)$
+^\[main.assertion.5\] .* assertion a==2: Success$
+^\[main.assertion.6\] .* assertion a==1: Failure \(if reachable\)$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-struct/sensitivity_test_constants_pointer_to_constants_struct.c b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-struct/sensitivity_test_constants_pointer_to_constants_struct.c
new file mode 100644
index 00000000000..8f86047a407
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-struct/sensitivity_test_constants_pointer_to_constants_struct.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/pointer_to_struct_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-struct/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-struct/test.desc
new file mode 100644
index 00000000000..c7abd5e6821
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-constants-struct/test.desc
@@ -0,0 +1,16 @@
+KNOWNBUG
+sensitivity_test_constants_pointer_to_constants_struct.c
+--variable --pointers --structs --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion \(\*p\).a==0: Success$
+^\[main.assertion.2\] .* assertion \(\*p\).a==1: Failure \(if reachable\)$
+^\[main.assertion.3\] .* assertion p->a==0: Success$
+^\[main.assertion.4\] .* assertion p->a==1: Failure \(if reachable\)$
+^\[main.assertion.5\] .* assertion p->b==2.0: Success$
+^\[main.assertion.6\] .* assertion p->b==1.0: Failure \(if reachable\)$
+--
+^warning: ignoring
+--
+The final two assertions are the wrong way round as modifying the pointer
+does not seem to be propogating through. See #96
diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/sensitivity_test_constants_pointer_to_two_value_array.c b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/sensitivity_test_constants_pointer_to_two_value_array.c
new file mode 100644
index 00000000000..082fe2e62c8
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/sensitivity_test_constants_pointer_to_two_value_array.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc
new file mode 100644
index 00000000000..7121e17040d
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-array/test.desc
@@ -0,0 +1,21 @@
+FUTURE
+sensitivity_test_constants_pointer_to_two_value_array.c
+--variable --pointers --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion p==&a\[0\]: Success$
+^\[main.assertion.2\] .* assertion \*p==1: Unknown$
+^\[main.assertion.3\] .* assertion q==p\+1: Unknown$
+^\[main.assertion.4\] .* assertion \*q==2: Unknown$
+^\[main.assertion.5\] .* assertion q-p==x: Unknown$
+^\[main.assertion.6\] .* assertion a\[1\]==4: Unknown$
+^\[main.assertion.7\] .* assertion \*r==2: Unknown$
+^\[main.assertion.8\] .* assertion \*r==1: Unknown$
+^\[main.assertion.9\] .* assertion \*s==0: Unknown$
+^\[main.assertion.10\] .* assertion \*s==1: Unknown$
+^\[main.assertion.11\] .* assertion t==p\+i: Unknown$
+^\[main.assertion.12\] .* assertion t-p==y: Unknown$
+^\[main.assertion.13\] .* assertion a\[i\]==5: Unknown$
+^\[main.assertion.14\] .* assertion a\[1\]==5: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/sensitivity_test_constants_pointer_to_two_value_struct.c b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/sensitivity_test_constants_pointer_to_two_value_struct.c
new file mode 100644
index 00000000000..8f86047a407
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/sensitivity_test_constants_pointer_to_two_value_struct.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/pointer_to_struct_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/test.desc
new file mode 100644
index 00000000000..a214499b34b
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-pointer-to-two-value-struct/test.desc
@@ -0,0 +1,13 @@
+FUTURE
+sensitivity_test_constants_pointer_to_two_value_struct.c
+--variable --pointers --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion \(\*p\).a==0: Unknown$
+^\[main.assertion.2\] .* assertion \(\*p\).a==1: Unknown$
+^\[main.assertion.3\] .* assertion p->a==0: Unknown$
+^\[main.assertion.4\] .* assertion p->a==1: Unknown$
+^\[main.assertion.5\] .* assertion p->b==2.0: Unknown$
+^\[main.assertion.6\] .* assertion p->b==1.0: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer/sensitivity_test_constants_pointer.c b/regression/goto-analyzer/sensitivity-test-constants-pointer/sensitivity_test_constants_pointer.c
new file mode 100644
index 00000000000..a2167bc68f4
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-pointer/sensitivity_test_constants_pointer.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/pointer_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc
new file mode 100644
index 00000000000..22c179f2233
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-pointer/test.desc
@@ -0,0 +1,21 @@
+FUTURE
+sensitivity_test_constants_pointer.c
+--variable --pointers --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x==&a: Success$
+^\[main.assertion.2\] .* assertion x==&b: Failure \(if reachable\)$
+^\[main.assertion.3\] .* assertion x==x2: Success$
+^\[main.assertion.4\] .* assertion x==y: Failure \(if reachable\)$
+^\[main.assertion.5\] .* assertion \*x==0: Success$
+^\[main.assertion.6\] .* assertion \*x==1: Failure \(if reachable\)$
+^\[main.assertion.7\] .* assertion \*x==1: Success$
+^\[main.assertion.8\] .* assertion \*x==0: Failure \(if reachable\)$
+^\[main.assertion.9\] .* assertion a==2: Success$
+^\[main.assertion.10\] .* assertion a==0: Failure \(if reachable\)$
+^\[main.assertion.11\] .* assertion x==&a: Success$
+^\[main.assertion.12\] .* assertion \*x==0: Unknown$
+^\[main.assertion.13\] .* assertion x==&a: Unknown$
+^\[main.assertion.14\] .* assertion x==&b: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/sensitivity_test_constants_struct_of_constants_array.c b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/sensitivity_test_constants_struct_of_constants_array.c
new file mode 100644
index 00000000000..d50aea1ea24
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/sensitivity_test_constants_struct_of_constants_array.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/struct_of_array_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/test.desc
new file mode 100644
index 00000000000..7b6ae24bf61
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-array/test.desc
@@ -0,0 +1,24 @@
+FUTURE
+sensitivity_test_constants_struct_of_constants_array.c
+--variable --structs --arrays --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x.a\[0\]==0: Success$
+^\[main.assertion.2\] .* assertion \*\(x.a\+0\)==0: Success$
+^\[main.assertion.3\] .* assertion \*\(0\+x.a\)==0: Success$
+^\[main.assertion.4\] .* assertion 0\[x.a\]==0: Success$
+^\[main.assertion.5\] .* assertion x.a\[0\]==0: Success$
+^\[main.assertion.6\] .* assertion x.a\[1\]==1: Success$
+^\[main.assertion.7\] .* assertion x.b\[0\]==3.0f: Success$
+^\[main.assertion.8\] .* assertion x.a\[0\]==0: Success$
+^\[main.assertion.9\] .* assertion x.a\[1\]==1: Success$
+^\[main.assertion.10\] .* assertion x.b\[2\]>0.0f: Unknown$
+^\[main.assertion.11\] .* assertion x.b\[2\]==15.0f: Unknown$
+^\[main.assertion.12\] .* assertion x.b\[2\]==1.0f: Unknown$
+^\[main.assertion.13\] .* assertion x.b\[0\]==3.0f: Success$
+^\[main.assertion.14\] .* assertion x.a\[0\]<12: Unknown$
+^\[main.assertion.15\] .* assertion x.a\[0\]>2: Unknown$
+^\[main.assertion.16\] .* assertion x.a\[0\]==0: Unknown$
+^\[main.assertion.17\] .* assertion x.a\[1\]==1: Success$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/sensitivity_test_constants_struct_of_constants_pointer.c b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/sensitivity_test_constants_struct_of_constants_pointer.c
new file mode 100644
index 00000000000..ab7d896ae5d
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/sensitivity_test_constants_struct_of_constants_pointer.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/struct_of_pointer_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/test.desc
new file mode 100644
index 00000000000..b278a7ed47c
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-pointer/test.desc
@@ -0,0 +1,33 @@
+FUTURE
+sensitivity_test_constants_struct_of_constants_pointer.c
+--variable --structs --pointers --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x.a==&a1: Success$
+^\[main.assertion.2\] .* assertion x.a==&a2: Failure \(if reachable\)$
+^\[main.assertion.3\] .* assertion x.b==&b1: Success$
+^\[main.assertion.4\] .* assertion x.b==&b2: Failure \(if reachable\)$
+^\[main.assertion.5\] .* assertion \*x.a==0: Success$
+^\[main.assertion.6\] .* assertion \*x.a==100: Failure \(if reachable\)$
+^\[main.assertion.7\] .* assertion \*x.b==10.0f: Success$
+^\[main.assertion.8\] .* assertion \*x.b==110.0f: Failure \(if reachable\)$
+^\[main.assertion.9\] .* assertion x.a==&a1: Success$
+^\[main.assertion.10\] .* assertion x.a==&a2: Failure \(if reachable\)$
+^\[main.assertion.11\] .* assertion \*x.a==0: Success$
+^\[main.assertion.12\] .* assertion \*x.a==100: Failure \(if reachable\)$
+^\[main.assertion.13\] .* assertion x.a==&a1: Success$
+^\[main.assertion.14\] .* assertion x.b==&b2: Unknown$
+^\[main.assertion.15\] .* assertion x.b==&b3: Unknown$
+^\[main.assertion.16\] .* assertion \*x.a==0: Success$
+^\[main.assertion.17\] .* assertion \*x.b==11.0f: Unknown$
+^\[main.assertion.18\] .* assertion \*x.b==12.0f: Unknown$
+^\[main.assertion.19\] .* assertion x.a==&a2: Unknown$
+^\[main.assertion.20\] .* assertion x.a==&a3: Unknown$
+^\[main.assertion.21\] .* assertion x.b==&b3: Unknown$
+^\[main.assertion.22\] .* assertion x.b==&b4: Unknown$
+^\[main.assertion.23\] .* assertion \*x.a==1: Unknown$
+^\[main.assertion.24\] .* assertion \*x.a==2: Unknown$
+^\[main.assertion.25\] .* assertion \*x.b==12.0f: Unknown$
+^\[main.assertion.26\] .* assertion \*x.b==13.0f: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/sensitivity_test_constants_struct_of_constants_struct.c b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/sensitivity_test_constants_struct_of_constants_struct.c
new file mode 100644
index 00000000000..ae2ab34d038
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/sensitivity_test_constants_struct_of_constants_struct.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/struct_of_struct_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/test.desc
new file mode 100644
index 00000000000..28f2e09614a
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-constants-struct/test.desc
@@ -0,0 +1,18 @@
+FUTURE
+sensitivity_test_constants_struct_of_constants_struct.c
+--variable --structs --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x.s1.a==0: Success$
+^\[main.assertion.2\] .* assertion x.s2.b==3.0f: Success$
+^\[main.assertion.3\] .* assertion x.s1.a==0: Success$
+^\[main.assertion.4\] .* assertion x.s1.a==10: Failure \(if reachable\)$
+^\[main.assertion.5\] .* assertion x.s1.b==1.0f: Success$
+^\[main.assertion.6\] .* assertion x.s2.b==3.0f: Unknown$
+^\[main.assertion.7\] .* assertion x.s2.b==0.0f: Unknown$
+^\[main.assertion.8\] .* assertion x.s1.a==20: Unknown$
+^\[main.assertion.9\] .* assertion x.s1.a<30: Unknown$
+^\[main.assertion.10\] .* assertion x.s2.a==22: Unknown$
+^\[main.assertion.11\] .* assertion x.s2.a<30: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/sensitivity_test_constants_struct_of_two_value_array.c b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/sensitivity_test_constants_struct_of_two_value_array.c
new file mode 100644
index 00000000000..d50aea1ea24
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/sensitivity_test_constants_struct_of_two_value_array.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/struct_of_array_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/test.desc
new file mode 100644
index 00000000000..30edb4b598c
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-array/test.desc
@@ -0,0 +1,24 @@
+FUTURE
+sensitivity_test_constants_struct_of_two_value_array.c
+--variable --structs --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x.a\[0\]==0: Unknown$
+^\[main.assertion.2\] .* assertion \*\(x.a\+0\)==0: Unknown$
+^\[main.assertion.3\] .* assertion \*\(0\+x.a\)==0: Unknown$
+^\[main.assertion.4\] .* assertion 0\[x.a\]==0: Unknown$
+^\[main.assertion.5\] .* assertion x.a\[0\]==0: Unknown$
+^\[main.assertion.6\] .* assertion x.a\[1\]==1: Unknown$
+^\[main.assertion.7\] .* assertion x.b\[0\]==3.0f: Unknown$
+^\[main.assertion.8\] .* assertion x.a\[0\]==0: Unknown$
+^\[main.assertion.9\] .* assertion x.a\[1\]==1: Unknown$
+^\[main.assertion.10\] .* assertion x.b\[2\]>0.0f: Unknown$
+^\[main.assertion.11\] .* assertion x.b\[2\]==15.0f: Unknown$
+^\[main.assertion.12\] .* assertion x.b\[2\]==1.0f: Unknown$
+^\[main.assertion.13\] .* assertion x.b\[0\]==3.0f: Unknown$
+^\[main.assertion.14\] .* assertion x.a\[0\]<12: Unknown$
+^\[main.assertion.15\] .* assertion x.a\[0\]>2: Unknown$
+^\[main.assertion.16\] .* assertion x.a\[0\]==0: Unknown$
+^\[main.assertion.17\] .* assertion x.a\[1\]==1: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/sensitivity_test_constants_struct_of_two_value_pointer.c b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/sensitivity_test_constants_struct_of_two_value_pointer.c
new file mode 100644
index 00000000000..ab7d896ae5d
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/sensitivity_test_constants_struct_of_two_value_pointer.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/struct_of_pointer_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/test.desc
new file mode 100644
index 00000000000..ea3a9cadb69
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-struct-of-two-value-pointer/test.desc
@@ -0,0 +1,33 @@
+FUTURE
+sensitivity_test_constants_struct_of_two_value_pointer.c
+--variable --structs --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x.a==&a1: Unknown$
+^\[main.assertion.2\] .* assertion x.a==&a2: Unknown$
+^\[main.assertion.3\] .* assertion x.b==&b1: Unknown$
+^\[main.assertion.4\] .* assertion x.b==&b2: Unknown$
+^\[main.assertion.5\] .* assertion \*x.a==0: Unknown$
+^\[main.assertion.6\] .* assertion \*x.a==100: Unknown$
+^\[main.assertion.7\] .* assertion \*x.b==10.0f: Unknown$
+^\[main.assertion.8\] .* assertion \*x.b==110.0f: Unknown$
+^\[main.assertion.9\] .* assertion x.a==&a1: Unknown$
+^\[main.assertion.10\] .* assertion x.a==&a2: Unknown$
+^\[main.assertion.11\] .* assertion \*x.a==0: Unknown$
+^\[main.assertion.12\] .* assertion \*x.a==100: Unknown$
+^\[main.assertion.13\] .* assertion x.a==&a1: Unknown$
+^\[main.assertion.14\] .* assertion x.b==&b2: Unknown$
+^\[main.assertion.15\] .* assertion x.b==&b3: Unknown$
+^\[main.assertion.16\] .* assertion \*x.a==0: Unknown$
+^\[main.assertion.17\] .* assertion \*x.b==11.0f: Unknown$
+^\[main.assertion.18\] .* assertion \*x.b==12.0f: Unknown$
+^\[main.assertion.19\] .* assertion x.a==&a2: Unknown$
+^\[main.assertion.20\] .* assertion x.a==&a3: Unknown$
+^\[main.assertion.21\] .* assertion x.b==&b3: Unknown$
+^\[main.assertion.22\] .* assertion x.b==&b4: Unknown$
+^\[main.assertion.23\] .* assertion \*x.a==1: Unknown$
+^\[main.assertion.24\] .* assertion \*x.a==2: Unknown$
+^\[main.assertion.25\] .* assertion \*x.b==12.0f: Unknown$
+^\[main.assertion.26\] .* assertion \*x.b==13.0f: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct/sensitivity_test_constants_struct.c b/regression/goto-analyzer/sensitivity-test-constants-struct/sensitivity_test_constants_struct.c
new file mode 100644
index 00000000000..946ec769d9e
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-struct/sensitivity_test_constants_struct.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/struct_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc b/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc
new file mode 100644
index 00000000000..64a15fcae85
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-constants-struct/test.desc
@@ -0,0 +1,16 @@
+FUTURE
+sensitivity_test_constants_struct.c
+--variable --structs --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x.a==0: Success$
+^\[main.assertion.2\] .* assertion x.a==1: Failure \(if reachable\)$
+^\[main.assertion.3\] .* assertion x.a==0: Success$
+^\[main.assertion.4\] .* assertion x.a==0: Success$
+^\[main.assertion.5\] .* assertion x.b>0.0f: Unknown$
+^\[main.assertion.6\] .* assertion x.b==1.0f: Unknown$
+^\[main.assertion.7\] .* assertion x.a<2: Unknown$
+^\[main.assertion.8\] .* assertion x.a>2: Unknown$
+^\[main.assertion.9\] .* assertion x.a==1: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/sensitivity_test_two_value_array_of_two_value_array.c b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/sensitivity_test_two_value_array_of_two_value_array.c
new file mode 100644
index 00000000000..103849f7a32
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/sensitivity_test_two_value_array_of_two_value_array.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/array_of_array_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/test.desc
new file mode 100644
index 00000000000..2c2c3ed15a8
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-array/test.desc
@@ -0,0 +1,73 @@
+FUTURE
+sensitivity_test_two_value_array_of_two_value_array.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion a\[1\]\[2\]==0: Unknown$
+^\[main.assertion.2\] .* assertion a\[1\]\[2\]==1: Unknown$
+^\[main.assertion.3\] .* assertion b\[1\]\[2\]==5: Unknown$
+^\[main.assertion.4\] .* assertion b\[1\]\[2\]==0: Unknown$
+^\[main.assertion.5\] .* assertion \*\(b\[1\]\+2\)==5: Unknown$
+^\[main.assertion.6\] .* assertion \*\(b\[1\]\+2\)==0: Unknown$
+^\[main.assertion.7\] .* assertion \(\*\(b\+1\)\)\[2\]==5: Unknown$
+^\[main.assertion.8\] .* assertion \(\*\(b\+1\)\)\[2\]==0: Unknown$
+^\[main.assertion.9\] .* assertion \*\(\*\(b\+1\)\+2\)==5: Unknown$
+^\[main.assertion.10\] .* assertion \*\(\*\(b\+1\)\+2\)==0: Unknown$
+^\[main.assertion.11\] .* assertion 1\[b\]\[2\]==5: Unknown$
+^\[main.assertion.12\] .* assertion 1\[b\]\[2\]==0: Unknown$
+^\[main.assertion.13\] .* assertion \*\(1\[b\]\+2\)==5: Unknown$
+^\[main.assertion.14\] .* assertion \*\(1\[b\]\+2\)==0: Unknown$
+^\[main.assertion.15\] .* assertion \(\*\(1\+b\)\)\[2\]==5: Unknown$
+^\[main.assertion.16\] .* assertion \(\*\(1\+b\)\)\[2\]==0: Unknown$
+^\[main.assertion.17\] .* assertion \*\(\*\(1\+b\)\+2\)==5: Unknown$
+^\[main.assertion.18\] .* assertion \*\(\*\(1\+b\)\+2\)==0: Unknown$
+^\[main.assertion.19\] .* assertion 2\[1\[b\]\]==5: Unknown$
+^\[main.assertion.20\] .* assertion 2\[1\[b\]\]==0: Unknown$
+^\[main.assertion.21\] .* assertion \*\(2\+1\[b\]\)==5: Unknown$
+^\[main.assertion.22\] .* assertion \*\(2\+1\[b\]\)==0: Unknown$
+^\[main.assertion.23\] .* assertion \*\(2\+\*\(1\+b\)\)==5: Unknown$
+^\[main.assertion.24\] .* assertion \*\(2\+\*\(1\+b\)\)==0: Unknown$
+^\[main.assertion.25\] .* assertion a\[0\]\[1\]==0: Unknown$
+^\[main.assertion.26\] .* assertion a\[0\]\[1\]==1: Unknown$
+^\[main.assertion.27\] .* assertion a\[0\]\[2\]==0: Unknown$
+^\[main.assertion.28\] .* assertion b\[0\]\[1\]==2: Unknown$
+^\[main.assertion.29\] .* assertion b\[0\]\[1\]==3: Unknown$
+^\[main.assertion.30\] .* assertion b\[0\]\[2\]==2: Unknown$
+^\[main.assertion.31\] .* assertion a\[i\]\[1\]==0: Unknown$
+^\[main.assertion.32\] .* assertion a\[i\]\[1\]==1: Unknown$
+^\[main.assertion.33\] .* assertion a\[1\]\[i\]==0: Unknown$
+^\[main.assertion.34\] .* assertion a\[1\]\[i\]==1: Unknown$
+^\[main.assertion.35\] .* assertion a\[i\]\[i\]==0: Unknown$
+^\[main.assertion.36\] .* assertion a\[i\]\[i\]==1: Unknown$
+^\[main.assertion.37\] .* assertion a\[j\]\[1\]==0: Unknown$
+^\[main.assertion.38\] .* assertion a\[j\]\[1\]==1: Unknown$
+^\[main.assertion.39\] .* assertion a\[1\]\[j\]==0: Unknown$
+^\[main.assertion.40\] .* assertion a\[1\]\[j\]==1: Unknown$
+^\[main.assertion.41\] .* assertion a\[j\]\[j\]==0: Unknown$
+^\[main.assertion.42\] .* assertion a\[j\]\[j\]==1: Unknown$
+^\[main.assertion.43\] .* assertion b\[i\]\[1\]==1: Unknown$
+^\[main.assertion.44\] .* assertion b\[i\]\[1\]==11: Unknown$
+^\[main.assertion.45\] .* assertion b\[1\]\[i\]==3: Unknown$
+^\[main.assertion.46\] .* assertion b\[1\]\[i\]==11: Unknown$
+^\[main.assertion.47\] .* assertion b\[i\]\[i\]==0: Unknown$
+^\[main.assertion.48\] .* assertion b\[i\]\[i\]==11: Unknown$
+^\[main.assertion.49\] .* assertion b\[j\]\[1\]==1: Unknown$
+^\[main.assertion.50\] .* assertion b\[j\]\[1\]==11: Unknown$
+^\[main.assertion.51\] .* assertion b\[1\]\[j\]==3: Unknown$
+^\[main.assertion.52\] .* assertion b\[1\]\[j\]==11: Unknown$
+^\[main.assertion.53\] .* assertion b\[j\]\[j\]==0: Unknown$
+^\[main.assertion.54\] .* assertion b\[j\]\[j\]==11: Unknown$
+^\[main.assertion.55\] .* assertion a\[100\]\[0\]==0: Unknown$
+^\[main.assertion.56\] .* assertion a\[0\]\[100\]==0: Unknown$
+^\[main.assertion.57\] .* assertion c==0: Success$
+^\[main.assertion.58\] .* assertion c==0: Success$
+^\[main.assertion.59\] .* assertion ei\[0\]\[1\]==1: Unknown$
+^\[main.assertion.60\] .* assertion ei\[0\]\[1\]==0: Unknown$
+^\[main.assertion.61\] .* assertion ei\[2\]\[1\]==0: Unknown$
+^\[main.assertion.62\] .* assertion ei\[2\]\[1\]==1: Unknown$
+^\[main.assertion.63\] .* assertion ej\[0\]\[1\]==0: Unknown$
+^\[main.assertion.64\] .* assertion ej\[2\]\[1\]==0: Unknown$
+^\[main.assertion.65\] .* assertion ek\[0\]\[1\]==0: Unknown$
+^\[main.assertion.66\] .* assertion c==0: Success$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/sensitivity_test_two_value_array_of_two_value_pointer.c b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/sensitivity_test_two_value_array_of_two_value_pointer.c
new file mode 100644
index 00000000000..66edcccfbfb
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/sensitivity_test_two_value_array_of_two_value_pointer.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/array_of_pointer_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc
new file mode 100644
index 00000000000..f9de8e20a03
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-array-of-two-value-pointer/test.desc
@@ -0,0 +1,71 @@
+FUTURE
+sensitivity_test_two_value_array_of_two_value_pointer.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion a\[1\]==&a0: Unknown$
+^\[main.assertion.2\] .* assertion a\[1\]==&a3: Unknown$
+^\[main.assertion.3\] .* assertion \*a\[1\]==0: Unknown$
+^\[main.assertion.4\] .* assertion \*a\[1\]==3: Unknown$
+^\[main.assertion.5\] .* assertion b\[1\]==&b1: Unknown$
+^\[main.assertion.6\] .* assertion b\[1\]==&b3: Unknown$
+^\[main.assertion.7\] .* assertion \*b\[1\]==11: Unknown$
+^\[main.assertion.8\] .* assertion \*b\[1\]==13: Unknown$
+^\[main.assertion.9\] .* assertion \*\(b\+1\)==&b1: Unknown$
+^\[main.assertion.10\] .* assertion \*\(b\+1\)==&b3: Unknown$
+^\[main.assertion.11\] .* assertion \*\(1\+b\)==&b1: Unknown$
+^\[main.assertion.12\] .* assertion \*\(1\+b\)==&b3: Unknown$
+^\[main.assertion.13\] .* assertion 1\[b\]==&b1: Unknown$
+^\[main.assertion.14\] .* assertion 1\[b\]==&b3: Unknown$
+^\[main.assertion.15\] .* assertion \*\*\(b\+1\)==11: Unknown$
+^\[main.assertion.16\] .* assertion \*\*\(b\+1\)==13: Unknown$
+^\[main.assertion.17\] .* assertion \*\*\(1\+b\)==11: Unknown$
+^\[main.assertion.18\] .* assertion \*\*\(1\+b\)==13: Unknown$
+^\[main.assertion.19\] .* assertion \*1\[b\]==11: Unknown$
+^\[main.assertion.20\] .* assertion \*1\[b\]==13: Unknown$
+^\[main.assertion.21\] .* assertion c\[0\]==&c0: Unknown$
+^\[main.assertion.22\] .* assertion c\[0\]==&c3: Unknown$
+^\[main.assertion.23\] .* assertion d\[0\]==&d0: Unknown$
+^\[main.assertion.24\] .* assertion d\[0\]==&d3: Unknown$
+^\[main.assertion.25\] .* assertion \*c\[0\]==20: Unknown$
+^\[main.assertion.26\] .* assertion \*c\[0\]==23: Unknown$
+^\[main.assertion.27\] .* assertion \*d\[0\]==30: Unknown$
+^\[main.assertion.28\] .* assertion \*d\[0\]==33: Unknown$
+^\[main.assertion.29\] .* assertion a\[i\]==&a0: Unknown$
+^\[main.assertion.30\] .* assertion a\[i\]==&a3: Unknown$
+^\[main.assertion.31\] .* assertion a\[j\]==&a0: Unknown$
+^\[main.assertion.32\] .* assertion a\[j\]==&a3: Unknown$
+^\[main.assertion.33\] .* assertion \*a\[i\]==0: Unknown$
+^\[main.assertion.34\] .* assertion \*a\[i\]==3: Unknown$
+^\[main.assertion.35\] .* assertion \*a\[j\]==0: Unknown$
+^\[main.assertion.36\] .* assertion \*a\[j\]==3: Unknown$
+^\[main.assertion.37\] .* assertion b\[i\]==&b0: Unknown$
+^\[main.assertion.38\] .* assertion b\[i\]==&b1: Unknown$
+^\[main.assertion.39\] .* assertion b\[j\]==&b0: Unknown$
+^\[main.assertion.40\] .* assertion b\[j\]==&b3: Unknown$
+^\[main.assertion.41\] .* assertion \*b\[i\]==10: Unknown$
+^\[main.assertion.42\] .* assertion \*b\[i\]==11: Unknown$
+^\[main.assertion.43\] .* assertion \*b\[j\]==10: Unknown$
+^\[main.assertion.44\] .* assertion \*b\[j\]==13: Unknown$
+^\[main.assertion.45\] .* assertion a\[100\]==&a2: Unknown$
+^\[main.assertion.46\] .* assertion \*a\[100\]==2: Unknown$
+^\[main.assertion.47\] .* assertion b\[1\]==&b1: Unknown$
+^\[main.assertion.48\] .* assertion \*b\[1\]==11: Unknown$
+^\[main.assertion.49\] .* assertion ei\[0\]==&ei1: Unknown$
+^\[main.assertion.50\] .* assertion ei\[0\]==&ei0: Unknown$
+^\[main.assertion.51\] .* assertion ei\[2\]==&ei0: Unknown$
+^\[main.assertion.52\] .* assertion ei\[2\]==&ei1: Unknown$
+^\[main.assertion.53\] .* assertion \*ei\[0\]==41: Unknown$
+^\[main.assertion.54\] .* assertion \*ei\[0\]==40: Unknown$
+^\[main.assertion.55\] .* assertion \*ei\[2\]==40: Unknown$
+^\[main.assertion.56\] .* assertion \*ei\[2\]==41: Unknown$
+^\[main.assertion.57\] .* assertion ej\[0\]==&ej0: Unknown$
+^\[main.assertion.58\] .* assertion ej\[2\]==&ej0: Unknown$
+^\[main.assertion.59\] .* assertion ej\[2\]==&ej1: Unknown$
+^\[main.assertion.60\] .* assertion \*ej\[0\]==50: Unknown$
+^\[main.assertion.61\] .* assertion \*ej\[2\]==50: Unknown$
+^\[main.assertion.62\] .* assertion \*ej\[2\]==51: Unknown$
+^\[main.assertion.63\] .* assertion ek\[0\]==&ek0: Unknown$
+^\[main.assertion.64\] .* assertion \*ek\[0\]==60: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-array/sensitivity_test_two_value_array.c b/regression/goto-analyzer/sensitivity-test-two-value-array/sensitivity_test_two_value_array.c
new file mode 100644
index 00000000000..e0a5a37a2a2
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-array/sensitivity_test_two_value_array.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/array_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-array/test.desc
new file mode 100644
index 00000000000..23ee78bd74f
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-array/test.desc
@@ -0,0 +1,39 @@
+FUTURE
+sensitivity_test_two_value_array.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion a\[1\]==0: Unknown$
+^\[main.assertion.2\] .* assertion a\[1\]==1: Unknown$
+^\[main.assertion.3\] .* assertion b\[1\]==0: Unknown$
+^\[main.assertion.4\] .* assertion b\[1\]==1: Unknown$
+^\[main.assertion.5\] .* assertion \*\(b\+1\)==0: Unknown$
+^\[main.assertion.6\] .* assertion \*\(b\+1\)==1: Unknown$
+^\[main.assertion.7\] .* assertion \*\(1\+b\)==0: Unknown$
+^\[main.assertion.8\] .* assertion \*\(1\+b\)==1: Unknown$
+^\[main.assertion.9\] .* assertion 1\[b\]==0: Unknown$
+^\[main.assertion.10\] .* assertion 1\[b\]==1: Unknown$
+^\[main.assertion.11\] .* assertion c\[0\]==0: Unknown$
+^\[main.assertion.12\] .* assertion c\[0\]==1: Unknown$
+^\[main.assertion.13\] .* assertion d\[0\]==0: Unknown$
+^\[main.assertion.14\] .* assertion d\[0\]==2: Unknown$
+^\[main.assertion.15\] .* assertion d\[1\]==0: Unknown$
+^\[main.assertion.16\] .* assertion a\[i\]==0: Unknown$
+^\[main.assertion.17\] .* assertion a\[i\]==1: Unknown$
+^\[main.assertion.18\] .* assertion a\[j\]==0: Unknown$
+^\[main.assertion.19\] .* assertion a\[j\]==1: Unknown$
+^\[main.assertion.20\] .* assertion b\[i\]==1: Unknown$
+^\[main.assertion.21\] .* assertion b\[i\]==0: Unknown$
+^\[main.assertion.22\] .* assertion b\[j\]==0: Unknown$
+^\[main.assertion.23\] .* assertion b\[j\]==1: Unknown$
+^\[main.assertion.24\] .* assertion a\[100\]==0: Unknown$
+^\[main.assertion.25\] .* assertion b\[1\]==0: Unknown$
+^\[main.assertion.26\] .* assertion ei\[0\]==1: Unknown$
+^\[main.assertion.27\] .* assertion ei\[0\]==0: Unknown$
+^\[main.assertion.28\] .* assertion ei\[2\]==0: Unknown$
+^\[main.assertion.29\] .* assertion ei\[2\]==1: Unknown$
+^\[main.assertion.30\] .* assertion ej\[0\]==0: Unknown$
+^\[main.assertion.31\] .* assertion ej\[2\]==0: Unknown$
+^\[main.assertion.32\] .* assertion ek\[0\]==0: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/sensitivity_test_two_value_pointer_to_two_value_array.c b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/sensitivity_test_two_value_pointer_to_two_value_array.c
new file mode 100644
index 00000000000..082fe2e62c8
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/sensitivity_test_two_value_pointer_to_two_value_array.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/pointer_to_array_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc
new file mode 100644
index 00000000000..974705f9fc1
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-array/test.desc
@@ -0,0 +1,21 @@
+FUTURE
+sensitivity_test_two_value_pointer_to_two_value_array.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion p==&a\[0\]: Unknown$
+^\[main.assertion.2\] .* assertion \*p==1: Unknown$
+^\[main.assertion.3\] .* assertion q==p\+1: Unknown$
+^\[main.assertion.4\] .* assertion \*q==2: Unknown$
+^\[main.assertion.5\] .* assertion q-p==x: Unknown$
+^\[main.assertion.6\] .* assertion a\[1\]==4: Unknown$
+^\[main.assertion.7\] .* assertion \*r==2: Unknown$
+^\[main.assertion.8\] .* assertion \*r==1: Unknown$
+^\[main.assertion.9\] .* assertion \*s==0: Unknown$
+^\[main.assertion.10\] .* assertion \*s==1: Unknown$
+^\[main.assertion.11\] .* assertion t==p\+i: Unknown$
+^\[main.assertion.12\] .* assertion t-p==y: Unknown$
+^\[main.assertion.13\] .* assertion a\[i\]==5: Unknown$
+^\[main.assertion.14\] .* assertion a\[1\]==5: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/sensitivity_test_two_value_pointer_to_two_value_pointer.c b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/sensitivity_test_two_value_pointer_to_two_value_pointer.c
new file mode 100644
index 00000000000..56e6edc1093
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/sensitivity_test_two_value_pointer_to_two_value_pointer.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/pointer_to_pointer_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/test.desc
new file mode 100644
index 00000000000..e3582834688
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-pointer/test.desc
@@ -0,0 +1,13 @@
+FUTURE
+sensitivity_test_two_value_pointer_to_two_value_pointer.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion \*\*x==0: Unknown$
+^\[main.assertion.2\] .* assertion \*\*x==1: Unknown$
+^\[main.assertion.3\] .* assertion \*\*x==1: Unknown$
+^\[main.assertion.4\] .* assertion \*\*x==0: Unknown$
+^\[main.assertion.5\] .* assertion a==2: Unknown$
+^\[main.assertion.6\] .* assertion a==1: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/sensitivity_test_two_value_pointer_to_two_value_struct.c b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/sensitivity_test_two_value_pointer_to_two_value_struct.c
new file mode 100644
index 00000000000..8f86047a407
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/sensitivity_test_two_value_pointer_to_two_value_struct.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/pointer_to_struct_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/test.desc
new file mode 100644
index 00000000000..56a0be48407
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer-to-two-value-struct/test.desc
@@ -0,0 +1,13 @@
+FUTURE
+sensitivity_test_two_value_pointer_to_two_value_struct.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion \(\*p\).a==0: Unknown$
+^\[main.assertion.2\] .* assertion \(\*p\).a==1: Unknown$
+^\[main.assertion.3\] .* assertion p->a==0: Unknown$
+^\[main.assertion.4\] .* assertion p->a==1: Unknown$
+^\[main.assertion.5\] .* assertion p->b==2.0: Unknown$
+^\[main.assertion.6\] .* assertion p->b==1.0: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer/sensitivity_test_two_value_pointer.c b/regression/goto-analyzer/sensitivity-test-two-value-pointer/sensitivity_test_two_value_pointer.c
new file mode 100644
index 00000000000..a2167bc68f4
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer/sensitivity_test_two_value_pointer.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/pointer_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-pointer/test.desc
new file mode 100644
index 00000000000..da9abe2464f
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-pointer/test.desc
@@ -0,0 +1,21 @@
+FUTURE
+sensitivity_test_two_value_pointer.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x==&a: Unknown$
+^\[main.assertion.2\] .* assertion x==&b: Unknown$
+^\[main.assertion.3\] .* assertion x==x2: Unknown$
+^\[main.assertion.4\] .* assertion x==y: Unknown$
+^\[main.assertion.5\] .* assertion \*x==0: Unknown$
+^\[main.assertion.6\] .* assertion \*x==1: Unknown$
+^\[main.assertion.7\] .* assertion \*x==1: Unknown$
+^\[main.assertion.8\] .* assertion \*x==0: Unknown$
+^\[main.assertion.9\] .* assertion a==2: Unknown$
+^\[main.assertion.10\] .* assertion a==0: Unknown$
+^\[main.assertion.11\] .* assertion x==&a: Unknown$
+^\[main.assertion.12\] .* assertion \*x==0: Unknown$
+^\[main.assertion.13\] .* assertion x==&a: Unknown$
+^\[main.assertion.14\] .* assertion x==&b: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/sensitivity_test_two_value_struct_of_two_value_array.c b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/sensitivity_test_two_value_struct_of_two_value_array.c
new file mode 100644
index 00000000000..d50aea1ea24
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/sensitivity_test_two_value_struct_of_two_value_array.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/struct_of_array_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/test.desc
new file mode 100644
index 00000000000..e8773cf68fc
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-array/test.desc
@@ -0,0 +1,24 @@
+FUTURE
+sensitivity_test_two_value_struct_of_two_value_array.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x.a\[0\]==0: Unknown$
+^\[main.assertion.2\] .* assertion \*\(x.a\+0\)==0: Unknown$
+^\[main.assertion.3\] .* assertion \*\(0\+x.a\)==0: Unknown$
+^\[main.assertion.4\] .* assertion 0\[x.a\]==0: Unknown$
+^\[main.assertion.5\] .* assertion x.a\[0\]==0: Unknown$
+^\[main.assertion.6\] .* assertion x.a\[1\]==1: Unknown$
+^\[main.assertion.7\] .* assertion x.b\[0\]==3.0f: Unknown$
+^\[main.assertion.8\] .* assertion x.a\[0\]==0: Unknown$
+^\[main.assertion.9\] .* assertion x.a\[1\]==1: Unknown$
+^\[main.assertion.10\] .* assertion x.b\[2\]>0.0f: Unknown$
+^\[main.assertion.11\] .* assertion x.b\[2\]==15.0f: Unknown$
+^\[main.assertion.12\] .* assertion x.b\[2\]==1.0f: Unknown$
+^\[main.assertion.13\] .* assertion x.b\[0\]==3.0f: Unknown$
+^\[main.assertion.14\] .* assertion x.a\[0\]<12: Unknown$
+^\[main.assertion.15\] .* assertion x.a\[0\]>2: Unknown$
+^\[main.assertion.16\] .* assertion x.a\[0\]==0: Unknown$
+^\[main.assertion.17\] .* assertion x.a\[1\]==1: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/sensitivity_test_two_value_struct_of_two_value_pointer.c b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/sensitivity_test_two_value_struct_of_two_value_pointer.c
new file mode 100644
index 00000000000..ab7d896ae5d
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/sensitivity_test_two_value_struct_of_two_value_pointer.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/struct_of_pointer_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/test.desc
new file mode 100644
index 00000000000..06ebb29d047
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-pointer/test.desc
@@ -0,0 +1,33 @@
+FUTURE
+sensitivity_test_two_value_struct_of_two_value_pointer.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x.a==&a1: Unknown$
+^\[main.assertion.2\] .* assertion x.a==&a2: Unknown$
+^\[main.assertion.3\] .* assertion x.b==&b1: Unknown$
+^\[main.assertion.4\] .* assertion x.b==&b2: Unknown$
+^\[main.assertion.5\] .* assertion \*x.a==0: Unknown$
+^\[main.assertion.6\] .* assertion \*x.a==100: Unknown$
+^\[main.assertion.7\] .* assertion \*x.b==10.0f: Unknown$
+^\[main.assertion.8\] .* assertion \*x.b==110.0f: Unknown$
+^\[main.assertion.9\] .* assertion x.a==&a1: Unknown$
+^\[main.assertion.10\] .* assertion x.a==&a2: Unknown$
+^\[main.assertion.11\] .* assertion \*x.a==0: Unknown$
+^\[main.assertion.12\] .* assertion \*x.a==100: Unknown$
+^\[main.assertion.13\] .* assertion x.a==&a1: Unknown$
+^\[main.assertion.14\] .* assertion x.b==&b2: Unknown$
+^\[main.assertion.15\] .* assertion x.b==&b3: Unknown$
+^\[main.assertion.16\] .* assertion \*x.a==0: Unknown$
+^\[main.assertion.17\] .* assertion \*x.b==11.0f: Unknown$
+^\[main.assertion.18\] .* assertion \*x.b==12.0f: Unknown$
+^\[main.assertion.19\] .* assertion x.a==&a2: Unknown$
+^\[main.assertion.20\] .* assertion x.a==&a3: Unknown$
+^\[main.assertion.21\] .* assertion x.b==&b3: Unknown$
+^\[main.assertion.22\] .* assertion x.b==&b4: Unknown$
+^\[main.assertion.23\] .* assertion \*x.a==1: Unknown$
+^\[main.assertion.24\] .* assertion \*x.a==2: Unknown$
+^\[main.assertion.25\] .* assertion \*x.b==12.0f: Unknown$
+^\[main.assertion.26\] .* assertion \*x.b==13.0f: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/sensitivity_test_two_value_struct_of_two_value_struct.c b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/sensitivity_test_two_value_struct_of_two_value_struct.c
new file mode 100644
index 00000000000..ae2ab34d038
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/sensitivity_test_two_value_struct_of_two_value_struct.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/struct_of_struct_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/test.desc
new file mode 100644
index 00000000000..450055d2be6
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-struct-of-two-value-struct/test.desc
@@ -0,0 +1,18 @@
+FUTURE
+sensitivity_test_two_value_struct_of_two_value_struct.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x.s1.a==0: Unknown$
+^\[main.assertion.2\] .* assertion x.s2.b==3.0f: Unknown$
+^\[main.assertion.3\] .* assertion x.s1.a==0: Unknown$
+^\[main.assertion.4\] .* assertion x.s1.a==10: Unknown$
+^\[main.assertion.5\] .* assertion x.s1.b==1.0f: Unknown$
+^\[main.assertion.6\] .* assertion x.s2.b==3.0f: Unknown$
+^\[main.assertion.7\] .* assertion x.s2.b==0.0f: Unknown$
+^\[main.assertion.8\] .* assertion x.s1.a==20: Unknown$
+^\[main.assertion.9\] .* assertion x.s1.a<30: Unknown$
+^\[main.assertion.10\] .* assertion x.s2.a==22: Unknown$
+^\[main.assertion.11\] .* assertion x.s2.a<30: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct/sensitivity_test_two_value_struct.c b/regression/goto-analyzer/sensitivity-test-two-value-struct/sensitivity_test_two_value_struct.c
new file mode 100644
index 00000000000..946ec769d9e
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-struct/sensitivity_test_two_value_struct.c
@@ -0,0 +1 @@
+#include "../sensitivity-test-common-files/struct_sensitivity_tests.c"
diff --git a/regression/goto-analyzer/sensitivity-test-two-value-struct/test.desc b/regression/goto-analyzer/sensitivity-test-two-value-struct/test.desc
new file mode 100644
index 00000000000..157a3b25968
--- /dev/null
+++ b/regression/goto-analyzer/sensitivity-test-two-value-struct/test.desc
@@ -0,0 +1,16 @@
+FUTURE
+sensitivity_test_two_value_struct.c
+--variable --verify
+^EXIT=0$
+^SIGNAL=0$
+^\[main.assertion.1\] .* assertion x.a==0: Unknown$
+^\[main.assertion.2\] .* assertion x.a==1: Unknown$
+^\[main.assertion.3\] .* assertion x.a==0: Unknown$
+^\[main.assertion.4\] .* assertion x.a==0: Unknown$
+^\[main.assertion.5\] .* assertion x.b>0.0f: Unknown$
+^\[main.assertion.6\] .* assertion x.b==1.0f: Unknown$
+^\[main.assertion.7\] .* assertion x.a<2: Unknown$
+^\[main.assertion.8\] .* assertion x.a>2: Unknown$
+^\[main.assertion.9\] .* assertion x.a==1: Unknown$
+--
+^warning: ignoring
diff --git a/regression/goto-instrument-typedef/Makefile b/regression/goto-instrument-typedef/Makefile
new file mode 100644
index 00000000000..08fe97ae88c
--- /dev/null
+++ b/regression/goto-instrument-typedef/Makefile
@@ -0,0 +1,31 @@
+
+default: tests.log
+
+test:
+	@if ! ../test.pl -c ../chain.sh ; then \
+		../failed-tests-printer.pl ; \
+		exit 1; \
+	fi
+
+tests.log:
+	@if ! ../test.pl -c ../chain.sh ; then \
+		../failed-tests-printer.pl ; \
+		exit 1; \
+	fi
+
+show:
+	@for dir in *; do \
+		if [ -d "$$dir" ]; then \
+			vim -o "$$dir/*.c" "$$dir/*.out"; \
+		fi; \
+	done;
+
+clean:
+	@for dir in *; do \
+		rm -f tests.log; \
+		if [ -d "$$dir" ]; then \
+			cd "$$dir"; \
+			rm -f *.out *.gb; \
+			cd ..; \
+		fi \
+	done
diff --git a/regression/goto-instrument-typedef/chain.sh b/regression/goto-instrument-typedef/chain.sh
new file mode 100755
index 00000000000..9cef4ffdfa4
--- /dev/null
+++ b/regression/goto-instrument-typedef/chain.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+SRC=../../../src
+
+GC=$SRC/goto-cc/goto-cc
+GI=$SRC/goto-instrument/goto-instrument
+
+OPTS=$1
+NAME=${2%.c}
+
+rm $NAME.gb
+$GC $NAME.c --function fun -o $NAME.gb
+echo $GI $OPTS $NAME.gb
+$GI $OPTS $NAME.gb
diff --git a/regression/goto-instrument-typedef/typedef-anon-struct1/main.c b/regression/goto-instrument-typedef/typedef-anon-struct1/main.c
new file mode 100644
index 00000000000..d1e7196a3b1
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-anon-struct1/main.c
@@ -0,0 +1,11 @@
+
+typedef struct
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun()
+{
+  MYSTRUCT mystruct_var = {.x = 3, .y = 2.1f};
+}
diff --git a/regression/goto-instrument-typedef/typedef-anon-struct1/test.desc b/regression/goto-instrument-typedef/typedef-anon-struct1/test.desc
new file mode 100644
index 00000000000..59aba0e01a6
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-anon-struct1/test.desc
@@ -0,0 +1,10 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: mystruct_var\nMode\.+: C\nType\.+: MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-anon-struct2/main.c b/regression/goto-instrument-typedef/typedef-anon-struct2/main.c
new file mode 100644
index 00000000000..35475513f7d
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-anon-struct2/main.c
@@ -0,0 +1,11 @@
+
+typedef struct
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun()
+{
+  MYSTRUCT mystruct_var  = {.x = 10, .y = 3.1f}, another_mystruct_var = {.x = 3, .y = 2.1f};
+}
diff --git a/regression/goto-instrument-typedef/typedef-anon-struct2/test.desc b/regression/goto-instrument-typedef/typedef-anon-struct2/test.desc
new file mode 100644
index 00000000000..490b6cc2623
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-anon-struct2/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: mystruct_var\nMode\.+: C\nType\.+: MYSTRUCT
+Base name\.+: another_mystruct_var\nMode\.+: C\nType\.+: MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-anon-union1/main.c b/regression/goto-instrument-typedef/typedef-anon-union1/main.c
new file mode 100644
index 00000000000..9322c77cb6e
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-anon-union1/main.c
@@ -0,0 +1,11 @@
+
+typedef union
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun()
+{
+  MYUNION myunion_var = {.y = 2.1f};
+}
diff --git a/regression/goto-instrument-typedef/typedef-anon-union1/test.desc b/regression/goto-instrument-typedef/typedef-anon-union1/test.desc
new file mode 100644
index 00000000000..86caf078d6a
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-anon-union1/test.desc
@@ -0,0 +1,10 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: myunion_var\nMode\.+: C\nType\.+: MYUNION
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-anon-union2/main.c b/regression/goto-instrument-typedef/typedef-anon-union2/main.c
new file mode 100644
index 00000000000..b2dd6594432
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-anon-union2/main.c
@@ -0,0 +1,11 @@
+
+typedef union
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun()
+{
+  MYUNION myunion_var = {.y = 2.1f}, another_myunion_var = {.y = 2.1f};
+}
diff --git a/regression/goto-instrument-typedef/typedef-anon-union2/test.desc b/regression/goto-instrument-typedef/typedef-anon-union2/test.desc
new file mode 100644
index 00000000000..8d8ca64aa93
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-anon-union2/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: myunion_var\nMode\.+: C\nType\.+: MYUNION
+Base name\.+: another_myunion_var\nMode\.+: C\nType\.+: MYUNION
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-const-struct1/main.c b/regression/goto-instrument-typedef/typedef-const-struct1/main.c
new file mode 100644
index 00000000000..ab8137e82e4
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-const-struct1/main.c
@@ -0,0 +1,12 @@
+
+typedef struct tag_struct_name
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun()
+{
+  const struct tag_struct_name tag_struct_var = {.x = 1, .y = 3.14f};
+  const MYSTRUCT mystruct_var = {.x = 3, .y = 2.1f};
+}
diff --git a/regression/goto-instrument-typedef/typedef-const-struct1/test.desc b/regression/goto-instrument-typedef/typedef-const-struct1/test.desc
new file mode 100644
index 00000000000..a6aad1f799a
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-const-struct1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_struct_var\nMode\.+: C\nType\.+: const struct tag_struct_name
+Base name\.+: mystruct_var\nMode\.+: C\nType\.+: const MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-const-type1/main.c b/regression/goto-instrument-typedef/typedef-const-type1/main.c
new file mode 100644
index 00000000000..8cd4a4346eb
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-const-type1/main.c
@@ -0,0 +1,8 @@
+
+typedef int MYINT;
+
+void fun()
+{
+  const int int_var = 3;
+  const MYINT myint_var = 5;
+}
diff --git a/regression/goto-instrument-typedef/typedef-const-type1/test.desc b/regression/goto-instrument-typedef/typedef-const-type1/test.desc
new file mode 100644
index 00000000000..481b097653f
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-const-type1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_var\nMode\.+: C\nType\.+: const signed int
+Base name\.+: myint_var\nMode\.+: C\nType\.+: const MYINT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-const-union1/main.c b/regression/goto-instrument-typedef/typedef-const-union1/main.c
new file mode 100644
index 00000000000..b8defe635a6
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-const-union1/main.c
@@ -0,0 +1,12 @@
+
+typedef union tag_union_name
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun()
+{
+  const union tag_union_name tag_union_var = {1};
+  const MYUNION myunion_var = {.y = 2.1f};
+}
diff --git a/regression/goto-instrument-typedef/typedef-const-union1/test.desc b/regression/goto-instrument-typedef/typedef-const-union1/test.desc
new file mode 100644
index 00000000000..cd303b85195
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-const-union1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_union_var\nMode\.+: C\nType\.+: const union tag_union_name
+Base name\.+: myunion_var\nMode\.+: C\nType\.+: const MYUNION
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-param-anon-struct1/main.c b/regression/goto-instrument-typedef/typedef-param-anon-struct1/main.c
new file mode 100644
index 00000000000..e8f3fb8fd7c
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-anon-struct1/main.c
@@ -0,0 +1,11 @@
+
+typedef struct
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun(MYSTRUCT mystruct_param)
+{
+
+}
diff --git a/regression/goto-instrument-typedef/typedef-param-anon-struct1/test.desc b/regression/goto-instrument-typedef/typedef-param-anon-struct1/test.desc
new file mode 100644
index 00000000000..537526b4422
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-anon-struct1/test.desc
@@ -0,0 +1,10 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: mystruct_param\nMode\.+: C\nType\.+: MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-param-anon-union1/main.c b/regression/goto-instrument-typedef/typedef-param-anon-union1/main.c
new file mode 100644
index 00000000000..71791d9adfc
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-anon-union1/main.c
@@ -0,0 +1,10 @@
+
+typedef union
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun(MYUNION myunion_param)
+{
+}
diff --git a/regression/goto-instrument-typedef/typedef-param-anon-union1/test.desc b/regression/goto-instrument-typedef/typedef-param-anon-union1/test.desc
new file mode 100644
index 00000000000..270316982a3
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-anon-union1/test.desc
@@ -0,0 +1,10 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: myunion_param\nMode\.+: C\nType\.+: MYUNION
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-param-struct1/main.c b/regression/goto-instrument-typedef/typedef-param-struct1/main.c
new file mode 100644
index 00000000000..a358c15a030
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-struct1/main.c
@@ -0,0 +1,10 @@
+
+typedef struct tag_struct_name
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun(struct tag_struct_name tag_struct_param, MYSTRUCT mystruct_param)
+{
+}
diff --git a/regression/goto-instrument-typedef/typedef-param-struct1/test.desc b/regression/goto-instrument-typedef/typedef-param-struct1/test.desc
new file mode 100644
index 00000000000..c26ee458459
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-struct1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_struct_param\nMode\.+: C\nType\.+: struct tag_struct_name
+Base name\.+: mystruct_param\nMode\.+: C\nType\.+: MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-param-type1/main.c b/regression/goto-instrument-typedef/typedef-param-type1/main.c
new file mode 100644
index 00000000000..b4c915066b6
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-type1/main.c
@@ -0,0 +1,7 @@
+
+typedef int MYINT;
+
+void fun(int int_param, MYINT myint_param)
+{
+
+}
diff --git a/regression/goto-instrument-typedef/typedef-param-type1/test.desc b/regression/goto-instrument-typedef/typedef-param-type1/test.desc
new file mode 100644
index 00000000000..050ac22b315
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-type1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_param\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_param\nMode\.+: C\nType\.+: MYINT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-param-type2/main.c b/regression/goto-instrument-typedef/typedef-param-type2/main.c
new file mode 100644
index 00000000000..b5974fb6bbb
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-type2/main.c
@@ -0,0 +1,8 @@
+
+typedef int MYINT;
+typedef int ALTINT;
+
+void fun(int int_param, MYINT myint_param, ALTINT altint_param)
+{
+
+}
diff --git a/regression/goto-instrument-typedef/typedef-param-type2/test.desc b/regression/goto-instrument-typedef/typedef-param-type2/test.desc
new file mode 100644
index 00000000000..53cdc42193e
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-type2/test.desc
@@ -0,0 +1,12 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_param\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_param\nMode\.+: C\nType\.+: MYINT
+Base name\.+: altint_param\nMode\.+: C\nType\.+: ALTINT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-param-type3/main.c b/regression/goto-instrument-typedef/typedef-param-type3/main.c
new file mode 100644
index 00000000000..4d542e10c13
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-type3/main.c
@@ -0,0 +1,7 @@
+
+typedef int MYINT;
+typedef MYINT CHAINEDINT;
+
+void fun(int int_param, MYINT myint_param, CHAINEDINT chainedint_param)
+{
+}
diff --git a/regression/goto-instrument-typedef/typedef-param-type3/test.desc b/regression/goto-instrument-typedef/typedef-param-type3/test.desc
new file mode 100644
index 00000000000..6ba9d61f8ca
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-type3/test.desc
@@ -0,0 +1,12 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_param\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_param\nMode\.+: C\nType\.+: MYINT
+Base name\.+: chainedint_param\nMode\.+: C\nType\.+: CHAINEDINT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-param-union1/main.c b/regression/goto-instrument-typedef/typedef-param-union1/main.c
new file mode 100644
index 00000000000..8f961614e5d
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-union1/main.c
@@ -0,0 +1,10 @@
+
+typedef union tag_union_name
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun(union tag_union_name tag_union_param, MYUNION myunion_param)
+{
+}
diff --git a/regression/goto-instrument-typedef/typedef-param-union1/test.desc b/regression/goto-instrument-typedef/typedef-param-union1/test.desc
new file mode 100644
index 00000000000..466dd76ed52
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-param-union1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_union_param\nMode\.+: C\nType\.+: union tag_union_name
+Base name\.+: myunion_param\nMode\.+: C\nType\.+: MYUNION
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-return-anon-struct1/main.c b/regression/goto-instrument-typedef/typedef-return-anon-struct1/main.c
new file mode 100644
index 00000000000..0195b955cdd
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-anon-struct1/main.c
@@ -0,0 +1,12 @@
+
+typedef struct
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+MYSTRUCT fun()
+{
+  MYSTRUCT return_variable = {.x = 1, .y = 3.14f};
+  return return_variable;
+}
diff --git a/regression/goto-instrument-typedef/typedef-return-anon-struct1/test.desc b/regression/goto-instrument-typedef/typedef-return-anon-struct1/test.desc
new file mode 100644
index 00000000000..47964f71f66
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-anon-struct1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: return\nMode\.+: C\nType\.+: MYSTRUCT
+Base name\.+: fun\nMode\.+: C\nType\.+: MYSTRUCT \(\)
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-return-anon-union1/main.c b/regression/goto-instrument-typedef/typedef-return-anon-union1/main.c
new file mode 100644
index 00000000000..3bc7d19d5b7
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-anon-union1/main.c
@@ -0,0 +1,15 @@
+
+typedef union
+{
+  int x;
+  float y;
+} MYUNION;
+
+
+MYUNION fun()
+{
+  MYUNION return_variable = {1};
+  return return_variable;
+}
+
+
diff --git a/regression/goto-instrument-typedef/typedef-return-anon-union1/test.desc b/regression/goto-instrument-typedef/typedef-return-anon-union1/test.desc
new file mode 100644
index 00000000000..5a8d1b2062d
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-anon-union1/test.desc
@@ -0,0 +1,10 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: fun\nMode\.+: C\nType\.+: MYUNION \(\)
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-return-struct1/main.c b/regression/goto-instrument-typedef/typedef-return-struct1/main.c
new file mode 100644
index 00000000000..30c1323555c
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-struct1/main.c
@@ -0,0 +1,20 @@
+
+typedef struct tag_struct_name
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+struct tag_struct_name fun()
+{
+  struct tag_struct_name return_variable = { .x = 1, .y = 3.14f};
+  return return_variable;
+}
+
+MYSTRUCT fun2()
+{
+  MYSTRUCT return_variable = { .x = 1, .y = 3.14f};
+  return return_variable;
+}
+
+
diff --git a/regression/goto-instrument-typedef/typedef-return-struct1/test.desc b/regression/goto-instrument-typedef/typedef-return-struct1/test.desc
new file mode 100644
index 00000000000..eade5942ac8
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-struct1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: fun\nMode\.+: C\nType\.+: struct tag_struct_name \(\)
+Base name\.+: fun2\nMode\.+: C\nType\.+: MYSTRUCT \(\)
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-return-type1/main.c b/regression/goto-instrument-typedef/typedef-return-type1/main.c
new file mode 100644
index 00000000000..1ba7f426f89
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-type1/main.c
@@ -0,0 +1,12 @@
+
+typedef int MYINT;
+
+int fun()
+{
+  return 4;
+}
+
+MYINT fun2()
+{
+  return 5;
+}
diff --git a/regression/goto-instrument-typedef/typedef-return-type1/test.desc b/regression/goto-instrument-typedef/typedef-return-type1/test.desc
new file mode 100644
index 00000000000..ba1b96ce6b6
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-type1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: fun\nMode\.+: C\nType\.+: signed int \(\)
+Base name\.+: fun2\nMode\.+: C\nType\.+: MYINT \(\)
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-return-type2/main.c b/regression/goto-instrument-typedef/typedef-return-type2/main.c
new file mode 100644
index 00000000000..0d94ab54da3
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-type2/main.c
@@ -0,0 +1,13 @@
+
+typedef int MYINT;
+typedef int ALTINT;
+
+MYINT fun()
+{
+
+}
+
+ALTINT fun2()
+{
+
+}
diff --git a/regression/goto-instrument-typedef/typedef-return-type2/test.desc b/regression/goto-instrument-typedef/typedef-return-type2/test.desc
new file mode 100644
index 00000000000..1ecc9ea8e90
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-type2/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: fun\nMode\.+: C\nType\.+: MYINT \(\)
+Base name\.+: fun2\nMode\.+: C\nType\.+: ALTINT \(\)
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-return-type3/main.c b/regression/goto-instrument-typedef/typedef-return-type3/main.c
new file mode 100644
index 00000000000..e246757c692
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-type3/main.c
@@ -0,0 +1,12 @@
+
+typedef int MYINT;
+typedef MYINT CHAINEDINT;
+
+MYINT fun()
+{
+}
+
+CHAINEDINT fun2()
+{
+
+}
\ No newline at end of file
diff --git a/regression/goto-instrument-typedef/typedef-return-type3/test.desc b/regression/goto-instrument-typedef/typedef-return-type3/test.desc
new file mode 100644
index 00000000000..2401af3ce8d
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-type3/test.desc
@@ -0,0 +1,10 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+Base name\.+: fun\nMode\.+: C\nType\.+: MYINT \(\)
+Base name\.+: fun2\nMode\.+: C\nType\.+: CHAINEDINT \(\)
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-return-union1/main.c b/regression/goto-instrument-typedef/typedef-return-union1/main.c
new file mode 100644
index 00000000000..ad69cb04545
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-union1/main.c
@@ -0,0 +1,20 @@
+
+typedef union tag_union_name
+{
+  int x;
+  float y;
+} MYUNION;
+
+union tag_union_name fun()
+{
+  union tag_union_name return_variable = {1};
+  return return_variable;
+}
+
+MYUNION fun2()
+{
+  MYUNION return_variable = {1};
+  return return_variable;
+}
+
+
diff --git a/regression/goto-instrument-typedef/typedef-return-union1/test.desc b/regression/goto-instrument-typedef/typedef-return-union1/test.desc
new file mode 100644
index 00000000000..0855b28f479
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-return-union1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: fun\nMode\.+: C\nType\.+: union tag_union_name \(\)
+Base name\.+: fun2\nMode\.+: C\nType\.+: MYUNION \(\)
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-struct1/main.c b/regression/goto-instrument-typedef/typedef-struct1/main.c
new file mode 100644
index 00000000000..dac5abf77b8
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-struct1/main.c
@@ -0,0 +1,12 @@
+
+typedef struct tag_struct_name
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun()
+{
+  struct tag_struct_name tag_struct_var = {.x = 1, .y = 3.14f};
+  MYSTRUCT mystruct_var = {.x = 3, .y = 2.1f};
+}
diff --git a/regression/goto-instrument-typedef/typedef-struct1/test.desc b/regression/goto-instrument-typedef/typedef-struct1/test.desc
new file mode 100644
index 00000000000..6a02f2d2174
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-struct1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_struct_var\nMode\.+: C\nType\.+: struct tag_struct_name
+Base name\.+: mystruct_var\nMode\.+: C\nType\.+: MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-struct2/main.c b/regression/goto-instrument-typedef/typedef-struct2/main.c
new file mode 100644
index 00000000000..dac5abf77b8
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-struct2/main.c
@@ -0,0 +1,12 @@
+
+typedef struct tag_struct_name
+{
+  int x;
+  float y;
+} MYSTRUCT;
+
+void fun()
+{
+  struct tag_struct_name tag_struct_var = {.x = 1, .y = 3.14f};
+  MYSTRUCT mystruct_var = {.x = 3, .y = 2.1f};
+}
diff --git a/regression/goto-instrument-typedef/typedef-struct2/test.desc b/regression/goto-instrument-typedef/typedef-struct2/test.desc
new file mode 100644
index 00000000000..6a02f2d2174
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-struct2/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_struct_var\nMode\.+: C\nType\.+: struct tag_struct_name
+Base name\.+: mystruct_var\nMode\.+: C\nType\.+: MYSTRUCT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-type1/main.c b/regression/goto-instrument-typedef/typedef-type1/main.c
new file mode 100644
index 00000000000..43f028c7772
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-type1/main.c
@@ -0,0 +1,8 @@
+
+typedef int MYINT;
+
+void fun()
+{
+  int int_var = 3;
+  MYINT myint_var = 5;
+}
diff --git a/regression/goto-instrument-typedef/typedef-type1/test.desc b/regression/goto-instrument-typedef/typedef-type1/test.desc
new file mode 100644
index 00000000000..7599f1759c0
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-type1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_var\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_var\nMode\.+: C\nType\.+: MYINT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-type2/main.c b/regression/goto-instrument-typedef/typedef-type2/main.c
new file mode 100644
index 00000000000..acb1cce2da4
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-type2/main.c
@@ -0,0 +1,10 @@
+
+typedef int MYINT;
+typedef int ALTINT;
+
+void fun()
+{
+  int int_var = 3;
+  MYINT myint_var = 5;
+  ALTINT altint_var = 7;
+}
diff --git a/regression/goto-instrument-typedef/typedef-type2/test.desc b/regression/goto-instrument-typedef/typedef-type2/test.desc
new file mode 100644
index 00000000000..3cf1e50a5a5
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-type2/test.desc
@@ -0,0 +1,12 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_var\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_var\nMode\.+: C\nType\.+: MYINT
+Base name\.+: altint_var\nMode\.+: C\nType\.+: ALTINT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-type3/main.c b/regression/goto-instrument-typedef/typedef-type3/main.c
new file mode 100644
index 00000000000..5855e0c24cb
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-type3/main.c
@@ -0,0 +1,10 @@
+
+typedef int MYINT;
+typedef MYINT CHAINEDINT;
+
+void fun()
+{
+  int int_var = 3;
+  MYINT myint_var = 5;
+  CHAINEDINT chainedint_var = 5;
+}
diff --git a/regression/goto-instrument-typedef/typedef-type3/test.desc b/regression/goto-instrument-typedef/typedef-type3/test.desc
new file mode 100644
index 00000000000..aca9069695c
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-type3/test.desc
@@ -0,0 +1,12 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_var\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_var\nMode\.+: C\nType\.+: MYINT
+Base name\.+: chainedint_var\nMode\.+: C\nType\.+: CHAINEDINT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-type4/main.c b/regression/goto-instrument-typedef/typedef-type4/main.c
new file mode 100644
index 00000000000..aa2ec9ad7fb
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-type4/main.c
@@ -0,0 +1,8 @@
+
+typedef int MYINT;
+
+void fun()
+{
+  int int_var = 3;
+  MYINT myint_var = 5, another_myint_var = 10;
+}
diff --git a/regression/goto-instrument-typedef/typedef-type4/test.desc b/regression/goto-instrument-typedef/typedef-type4/test.desc
new file mode 100644
index 00000000000..28163714070
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-type4/test.desc
@@ -0,0 +1,12 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: int_var\nMode\.+: C\nType\.+: signed int
+Base name\.+: myint_var\nMode\.+: C\nType\.+: MYINT
+Base name\.+: another_myint_var\nMode\.+: C\nType\.+: MYINT
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-union1/main.c b/regression/goto-instrument-typedef/typedef-union1/main.c
new file mode 100644
index 00000000000..6f56f3c731b
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-union1/main.c
@@ -0,0 +1,12 @@
+
+typedef union tag_union_name
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun()
+{
+  union tag_union_name tag_union_var = {1};
+  MYUNION myunion_var = {.y = 2.1f};
+}
diff --git a/regression/goto-instrument-typedef/typedef-union1/test.desc b/regression/goto-instrument-typedef/typedef-union1/test.desc
new file mode 100644
index 00000000000..8502d149cb1
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-union1/test.desc
@@ -0,0 +1,11 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_union_var\nMode\.+: C\nType\.+: union tag_union_name
+Base name\.+: myunion_var\nMode\.+: C\nType\.+: MYUNION
+--
+warning: ignoring
diff --git a/regression/goto-instrument-typedef/typedef-union2/main.c b/regression/goto-instrument-typedef/typedef-union2/main.c
new file mode 100644
index 00000000000..9ca707cf767
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-union2/main.c
@@ -0,0 +1,12 @@
+
+typedef union tag_union_name
+{
+  int x;
+  float y;
+} MYUNION;
+
+void fun()
+{
+  union tag_union_name tag_union_var = {1}, another_tag_union_var = {1};
+  MYUNION myunion_var = {.y = 2.1f}, another_myunion_var = {.y = 3.1f};
+}
diff --git a/regression/goto-instrument-typedef/typedef-union2/test.desc b/regression/goto-instrument-typedef/typedef-union2/test.desc
new file mode 100644
index 00000000000..0fc908a6ab5
--- /dev/null
+++ b/regression/goto-instrument-typedef/typedef-union2/test.desc
@@ -0,0 +1,13 @@
+CORE
+main.c
+"--show-symbol-table"
+// Enable multi-line checking
+activate-multi-line-match
+EXIT=0
+SIGNAL=0
+Base name\.+: tag_union_var\nMode\.+: C\nType\.+: union tag_union_name
+Base name\.+: another_tag_union_var\nMode\.+: C\nType\.+: union tag_union_name
+Base name\.+: myunion_var\nMode\.+: C\nType\.+: MYUNION
+Base name\.+: another_myunion_var\nMode\.+: C\nType\.+: MYUNION
+--
+warning: ignoring
diff --git a/regression/goto-instrument-wmm-core/Makefile b/regression/goto-instrument-wmm-core/Makefile
index c1f99d1da81..85c17bf622b 100644
--- a/regression/goto-instrument-wmm-core/Makefile
+++ b/regression/goto-instrument-wmm-core/Makefile
@@ -21,7 +21,7 @@ tests.log: ../test.pl
 clean:
 	@for dir in *; do \
                 if [ -d "$$dir" ]; then \
-                        rm $$dir/*.txt $$dir/*.dot $$dir/*.gb $$dir/*.out; \
+                        $(RM) $$dir/*.txt $$dir/*.dot $$dir/*.gb $$dir/*.out; \
                 fi; \
         done;
 
diff --git a/regression/goto-instrument/Makefile b/regression/goto-instrument/Makefile
index 08fe97ae88c..94605814b4a 100644
--- a/regression/goto-instrument/Makefile
+++ b/regression/goto-instrument/Makefile
@@ -22,10 +22,10 @@ show:
 
 clean:
 	@for dir in *; do \
-		rm -f tests.log; \
+		$(RM) tests.log; \
 		if [ -d "$$dir" ]; then \
 			cd "$$dir"; \
-			rm -f *.out *.gb; \
+			$(RM) *.out *.gb; \
 			cd ..; \
 		fi \
 	done
diff --git a/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/main.c b/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/main.c
new file mode 100644
index 00000000000..3fb230c83fd
--- /dev/null
+++ b/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/main.c
@@ -0,0 +1,34 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+const void_fp fp_tbl[] = {f2, f3 ,f4};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  fp_tbl[i]();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
\ No newline at end of file
diff --git a/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/test.desc b/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/test.desc
new file mode 100644
index 00000000000..f58b03a58b3
--- /dev/null
+++ b/regression/goto-instrument/approx-array-variable-const-fp-only-remove-const/test.desc
@@ -0,0 +1,16 @@
+CORE
+main.c
+--verbosity 10 --pointer-check --remove-const-function-pointers
+
+^\s*IF fp_tbl\[\(signed long int\)i\] == f2 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f3 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f4 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^\s*IF fp_tbl\[\(signed long int\)i\] == f1 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f5 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f6 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f7 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f8 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f9 THEN GOTO [0-9]$
+^warning: ignoring
diff --git a/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/main.c b/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/main.c
new file mode 100644
index 00000000000..7896e3402c0
--- /dev/null
+++ b/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/main.c
@@ -0,0 +1,34 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+const void_fp fp_tbl[] = {f2, f3 ,f4};
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func(int i)
+{
+  fp_tbl[i]();
+}
+
+int main()
+{
+  for(int i=0;i<3;i++)
+  {
+    func(i);
+  }
+
+  return 0;
+}
diff --git a/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/test.desc b/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/test.desc
new file mode 100644
index 00000000000..3d065f1a742
--- /dev/null
+++ b/regression/goto-instrument/approx-array-variable-const-fp-remove-all-fp/test.desc
@@ -0,0 +1,16 @@
+CORE
+main.c
+--verbosity 10 --pointer-check --remove-function-pointers
+
+^\s*IF fp_tbl\[\(signed long int\)i\] == f2 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f3 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f4 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^\s*IF fp_tbl\[\(signed long int\)i\] == f1 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f5 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f6 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f7 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f8 THEN GOTO [0-9]$
+^\s*IF fp_tbl\[\(signed long int\)i\] == f9 THEN GOTO [0-9]$
+^warning: ignoring
diff --git a/regression/goto-instrument/no-match-non-const-fp-only-remove-const/main.c b/regression/goto-instrument/no-match-non-const-fp-only-remove-const/main.c
new file mode 100644
index 00000000000..80c8c863ff5
--- /dev/null
+++ b/regression/goto-instrument/no-match-non-const-fp-only-remove-const/main.c
@@ -0,0 +1,31 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  void_fp fp = f2;
+  fp = f3;
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-instrument/no-match-non-const-fp-only-remove-const/test.desc b/regression/goto-instrument/no-match-non-const-fp-only-remove-const/test.desc
new file mode 100644
index 00000000000..3b016907a44
--- /dev/null
+++ b/regression/goto-instrument/no-match-non-const-fp-only-remove-const/test.desc
@@ -0,0 +1,8 @@
+CORE
+main.c
+--verbosity 10 --pointer-check --remove-const-function-pointers
+
+^\s*fp\(\);$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-instrument/no-match-non-const-fp-remove-all-fp/main.c b/regression/goto-instrument/no-match-non-const-fp-remove-all-fp/main.c
new file mode 100644
index 00000000000..80c8c863ff5
--- /dev/null
+++ b/regression/goto-instrument/no-match-non-const-fp-remove-all-fp/main.c
@@ -0,0 +1,31 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  void_fp fp = f2;
+  fp = f3;
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-instrument/no-match-non-const-fp-remove-all-fp/test.desc b/regression/goto-instrument/no-match-non-const-fp-remove-all-fp/test.desc
new file mode 100644
index 00000000000..3190d348aae
--- /dev/null
+++ b/regression/goto-instrument/no-match-non-const-fp-remove-all-fp/test.desc
@@ -0,0 +1,16 @@
+CORE
+main.c
+--verbosity 10 --pointer-check --remove-function-pointers
+
+^\s*IF fp == f1 THEN GOTO [0-9]$
+^\s*IF fp == f2 THEN GOTO [0-9]$
+^\s*IF fp == f3 THEN GOTO [0-9]$
+^\s*IF fp == f4 THEN GOTO [0-9]$
+^\s*IF fp == f5 THEN GOTO [0-9]$
+^\s*IF fp == f6 THEN GOTO [0-9]$
+^\s*IF fp == f7 THEN GOTO [0-9]$
+^\s*IF fp == f8 THEN GOTO [0-9]$
+^\s*IF fp == f9 THEN GOTO [0-9]$
+^SIGNAL=0$
+--
+^warning: ignoring
diff --git a/regression/goto-instrument/precise-const-fp-only-remove-const/main.c b/regression/goto-instrument/precise-const-fp-only-remove-const/main.c
new file mode 100644
index 00000000000..b4002c94e5e
--- /dev/null
+++ b/regression/goto-instrument/precise-const-fp-only-remove-const/main.c
@@ -0,0 +1,30 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = f2;
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-instrument/precise-const-fp-only-remove-const/test.desc b/regression/goto-instrument/precise-const-fp-only-remove-const/test.desc
new file mode 100644
index 00000000000..2304d56b239
--- /dev/null
+++ b/regression/goto-instrument/precise-const-fp-only-remove-const/test.desc
@@ -0,0 +1,7 @@
+CORE
+main.c
+--verbosity 10 --pointer-check --remove-const-function-pointers
+
+^\s*f2\(\);
+--
+^warning: ignoring
diff --git a/regression/goto-instrument/precise-const-fp-remove-all-fp/main.c b/regression/goto-instrument/precise-const-fp-remove-all-fp/main.c
new file mode 100644
index 00000000000..b4002c94e5e
--- /dev/null
+++ b/regression/goto-instrument/precise-const-fp-remove-all-fp/main.c
@@ -0,0 +1,30 @@
+#include 
+
+void f1 (void) { printf("%i\n", 1); }
+void f2 (void) { printf("%i\n", 2); }
+void f3 (void) { printf("%i\n", 3); }
+void f4 (void) { printf("%i\n", 4); }
+void f5 (void) { printf("%i\n", 5); }
+void f6 (void) { printf("%i\n", 6); }
+void f7 (void) { printf("%i\n", 7); }
+void f8 (void) { printf("%i\n", 8); }
+void f9 (void) { printf("%i\n", 9); }
+
+typedef void(*void_fp)(void);
+
+// There is a basic check that excludes all functions that aren't used anywhere
+// This ensures that check can't work in this example
+const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
+
+void func()
+{
+  const void_fp fp = f2;
+  fp();
+}
+
+int main()
+{
+  func();
+
+  return 0;
+}
diff --git a/regression/goto-instrument/precise-const-fp-remove-all-fp/test.desc b/regression/goto-instrument/precise-const-fp-remove-all-fp/test.desc
new file mode 100644
index 00000000000..dd072b1c232
--- /dev/null
+++ b/regression/goto-instrument/precise-const-fp-remove-all-fp/test.desc
@@ -0,0 +1,7 @@
+CORE
+main.c
+--verbosity 10 --pointer-check --remove-function-pointers
+
+^\s*f2\(\);
+--
+^warning: ignoring
diff --git a/regression/goto-instrument/slice01/test.desc b/regression/goto-instrument/slice01/test.desc
index 76cbcfa81bd..73b1ad786c4 100644
--- a/regression/goto-instrument/slice01/test.desc
+++ b/regression/goto-instrument/slice01/test.desc
@@ -1,6 +1,6 @@
-KNOWNBUG
+CORE
 main.c
---unwind 2 --full-slice
+--unwind 2 --full-slice --add-library
 ^EXIT=0$
 ^SIGNAL=0$
 ^VERIFICATION SUCCESSFUL$
diff --git a/regression/goto-instrument/slice13/main.c b/regression/goto-instrument/slice13/main.c
index 3354961512a..a24498017a7 100644
--- a/regression/goto-instrument/slice13/main.c
+++ b/regression/goto-instrument/slice13/main.c
@@ -17,7 +17,9 @@ void test (int mode, double d, float result) {
 
 int main (void)
 {
+#ifdef __GNUC__
   // Nearer to 0x1.fffffep+127 than to 0x1.000000p+128
   test(FE_UPWARD, 0x1.fffffe0000001p+127, +INFINITY);
+#endif
   return 1;
 }
diff --git a/regression/goto-instrument/slice13/test.desc b/regression/goto-instrument/slice13/test.desc
index cc8dd41ed5f..50181efa86b 100644
--- a/regression/goto-instrument/slice13/test.desc
+++ b/regression/goto-instrument/slice13/test.desc
@@ -1,8 +1,6 @@
-KNOWNBUG
+CORE
 main.c
---floatbv --full-slice
+--full-slice --add-library
 ^EXIT=0$
 ^SIGNAL=0$
 ^VERIFICATION SUCCESSFUL$
---
-^warning: ignoring
diff --git a/regression/goto-instrument/slice16/test.desc b/regression/goto-instrument/slice16/test.desc
index 846baaf2a8b..ab6fd2dd827 100644
--- a/regression/goto-instrument/slice16/test.desc
+++ b/regression/goto-instrument/slice16/test.desc
@@ -1,8 +1,6 @@
-KNOWNBUG
+CORE
 main.c
 --full-slice --unwind 2
 ^EXIT=0$
 ^SIGNAL=0$
 ^VERIFICATION SUCCESSFUL$
---
-^warning: ignoring
diff --git a/regression/k-induction/Makefile b/regression/k-induction/Makefile
index 009b420f259..bfd7ece4734 100644
--- a/regression/k-induction/Makefile
+++ b/regression/k-induction/Makefile
@@ -12,3 +12,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/symex-infeasibility/Makefile b/regression/symex-infeasibility/Makefile
index d8a99eec731..120e9a347c0 100644
--- a/regression/symex-infeasibility/Makefile
+++ b/regression/symex-infeasibility/Makefile
@@ -12,3 +12,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/symex/Makefile b/regression/symex/Makefile
index d8a99eec731..120e9a347c0 100644
--- a/regression/symex/Makefile
+++ b/regression/symex/Makefile
@@ -12,3 +12,8 @@ show:
 			vim -o "$$dir/*.c" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/taint/Makefile b/regression/taint/Makefile
index 5701431a37e..40dbe9c53be 100644
--- a/regression/taint/Makefile
+++ b/regression/taint/Makefile
@@ -12,3 +12,8 @@ show:
 			vim -o "$$dir/*.java" "$$dir/*.out"; \
 		fi; \
 	done;
+
+clean:
+	find -name '*.out' -execdir $(RM) '{}' \;
+	find -name '*.gb' -execdir $(RM) '{}' \;
+	$(RM) tests.log
diff --git a/regression/test-script/Makefile b/regression/test-script/Makefile
index ba7db5e6250..ee6eaf02884 100644
--- a/regression/test-script/Makefile
+++ b/regression/test-script/Makefile
@@ -37,10 +37,10 @@ show:
 
 clean:
 	@for dir in *; do \
-		rm -f tests.log; \
+		$(RM) tests.log; \
 		if [ -d "$$dir" ]; then \
 			cd "$$dir"; \
-			rm -f *.out *.gb; \
+			$(RM) *.out *.gb; \
 			cd ..; \
 		fi \
 	done
diff --git a/src/analyses/Makefile b/src/analyses/Makefile
index 89f14e4f768..e05d5be0c42 100644
--- a/src/analyses/Makefile
+++ b/src/analyses/Makefile
@@ -6,7 +6,9 @@ SRC = natural_loops.cpp is_threaded.cpp dirty.cpp interval_analysis.cpp \
       local_bitvector_analysis.cpp dependence_graph.cpp \
       constant_propagator.cpp replace_symbol_ext.cpp \
       flow_insensitive_analysis.cpp \
-      custom_bitvector_analysis.cpp escape_analysis.cpp global_may_alias.cpp
+      custom_bitvector_analysis.cpp escape_analysis.cpp global_may_alias.cpp \
+      does_remove_const.cpp \
+      # Empty last line
 
 INCLUDES= -I ..
 
diff --git a/src/analyses/ai.cpp b/src/analyses/ai.cpp
index 06dd02af83f..2d1f4f6b986 100644
--- a/src/analyses/ai.cpp
+++ b/src/analyses/ai.cpp
@@ -81,6 +81,158 @@ void ai_baset::output(
 
 /*******************************************************************\
 
+Function: ai_baset::output_json
+
+  Inputs: The namespace and goto_functions
+
+ Outputs: The JSON object
+
+ Purpose: Output the domains for the whole program as JSON
+
+\*******************************************************************/
+
+jsont ai_baset::output_json(
+  const namespacet &ns,
+  const goto_functionst &goto_functions) const
+{
+  json_objectt result;
+
+  forall_goto_functions(f_it, goto_functions)
+  {
+    if(f_it->second.body_available())
+    {
+      result[id2string(f_it->first)]=
+        output_json(ns, f_it->second.body, f_it->first);
+    }
+    else
+    {
+      result[id2string(f_it->first)]=json_arrayt();
+    }
+  }
+
+  return result;
+}
+
+/*******************************************************************\
+
+Function: ai_baset::output_json
+
+  Inputs: The namespace, goto_program and it's identifier
+
+ Outputs: The JSON object
+
+ Purpose: Output the domains for a single function as JSON
+
+\*******************************************************************/
+
+jsont ai_baset::output_json(
+  const namespacet &ns,
+  const goto_programt &goto_program,
+  const irep_idt &identifier) const
+{
+  json_arrayt contents;
+
+  forall_goto_program_instructions(i_it, goto_program)
+  {
+    json_objectt location;
+    location["locationNumber"]=
+      json_numbert(std::to_string(i_it->location_number));
+    location["sourceLocation"]=
+      json_stringt(i_it->source_location.as_string());
+    location["domain"]=find_state(i_it).output_json(*this, ns);
+
+    // Ideally we need output_instruction_json
+    std::ostringstream out;
+    goto_program.output_instruction(ns, identifier, out, i_it);
+    location["instruction"]=json_stringt(out.str());
+
+    contents.push_back(location);
+  }
+
+  return contents;
+}
+
+/*******************************************************************\
+
+Function: ai_baset::output_xml
+
+  Inputs: The namespace and goto_functions
+
+ Outputs: The XML object
+
+ Purpose: Output the domains for the whole program as XML
+
+\*******************************************************************/
+
+xmlt ai_baset::output_xml(
+  const namespacet &ns,
+  const goto_functionst &goto_functions) const
+{
+  xmlt program("program");
+
+  forall_goto_functions(f_it, goto_functions)
+  {
+    xmlt function("function");
+    function.set_attribute("name", id2string(f_it->first));
+    function.set_attribute(
+      "body_available",
+      f_it->second.body_available() ? "true" : "false");
+
+    if(f_it->second.body_available())
+    {
+      function.new_element(output_xml(ns, f_it->second.body, f_it->first));
+    }
+
+    program.new_element(function);
+  }
+
+  return program;
+}
+
+/*******************************************************************\
+
+Function: ai_baset::output_xml
+
+  Inputs: The namespace, goto_program and it's identifier
+
+ Outputs: The XML object
+
+ Purpose: Output the domains for a single function as XML
+
+\*******************************************************************/
+
+xmlt ai_baset::output_xml(
+  const namespacet &ns,
+  const goto_programt &goto_program,
+  const irep_idt &identifier) const
+{
+  xmlt function_body;
+
+  forall_goto_program_instructions(i_it, goto_program)
+  {
+    xmlt location;
+    location.set_attribute(
+      "location_number",
+      std::to_string(i_it->location_number));
+    location.set_attribute(
+      "source_location",
+      i_it->source_location.as_string());
+
+    location.new_element(find_state(i_it).output_xml(*this, ns));
+
+    // Ideally we need output_instruction_xml
+    std::ostringstream out;
+    goto_program.output_instruction(ns, identifier, out, i_it);
+    location.set_attribute("instruction", out.str());
+
+    function_body.new_element(location);
+  }
+
+  return function_body;
+}
+
+/*******************************************************************\
+
 Function: ai_baset::entry_state
 
   Inputs:
diff --git a/src/analyses/ai.h b/src/analyses/ai.h
index c506cbbeb08..2894cde3b10 100644
--- a/src/analyses/ai.h
+++ b/src/analyses/ai.h
@@ -11,6 +11,10 @@ Author: Daniel Kroening, kroening@kroening.com
 
 #include 
 #include 
+#include 
+
+#include 
+#include 
 
 #include 
 
@@ -53,6 +57,27 @@ class ai_domain_baset
   {
   }
 
+  virtual jsont output_json(
+    const ai_baset &ai,
+    const namespacet &ns) const
+  {
+    std::ostringstream out;
+    output(out, ai, ns);
+    json_stringt json(out.str());
+    return json;
+  }
+
+  virtual xmlt output_xml(
+    const ai_baset &ai,
+    const namespacet &ns) const
+  {
+    std::ostringstream out;
+    output(out, ai, ns);
+    xmlt xml("domain");
+    xml.data=out.str();
+    return xml;
+  }
+
   // no states
   virtual void make_bottom()=0;
 
@@ -157,6 +182,58 @@ class ai_baset
     output(ns, goto_function.body, "", out);
   }
 
+
+  virtual jsont output_json(
+    const namespacet &ns,
+    const goto_functionst &goto_functions) const;
+
+  jsont output_json(
+    const goto_modelt &goto_model) const
+  {
+    const namespacet ns(goto_model.symbol_table);
+    return output_json(ns, goto_model.goto_functions);
+  }
+
+  jsont output_json(
+    const namespacet &ns,
+    const goto_programt &goto_program) const
+  {
+    return output_json(ns, goto_program, "");
+  }
+
+  jsont output_json(
+    const namespacet &ns,
+    const goto_functionst::goto_functiont &goto_function) const
+  {
+    return output_json(ns, goto_function.body, "");
+  }
+
+
+  virtual xmlt output_xml(
+    const namespacet &ns,
+    const goto_functionst &goto_functions) const;
+
+  xmlt output_xml(
+    const goto_modelt &goto_model) const
+  {
+    const namespacet ns(goto_model.symbol_table);
+    return output_xml(ns, goto_model.goto_functions);
+  }
+
+  xmlt output_xml(
+    const namespacet &ns,
+    const goto_programt &goto_program) const
+  {
+    return output_xml(ns, goto_program, "");
+  }
+
+  xmlt output_xml(
+    const namespacet &ns,
+    const goto_functionst::goto_functiont &goto_function) const
+  {
+    return output_xml(ns, goto_function.body, "");
+  }
+
 protected:
   // overload to add a factory
   virtual void initialize(const goto_programt &);
@@ -172,6 +249,17 @@ class ai_baset
     const irep_idt &identifier,
     std::ostream &out) const;
 
+  virtual jsont output_json(
+    const namespacet &ns,
+    const goto_programt &goto_program,
+    const irep_idt &identifier) const;
+
+  virtual xmlt output_xml(
+    const namespacet &ns,
+    const goto_programt &goto_program,
+    const irep_idt &identifier) const;
+
+
   // the work-queue is sorted by location number
   typedef std::map working_sett;
 
diff --git a/src/analyses/cfg_dominators.h b/src/analyses/cfg_dominators.h
index 1a4d6090f47..930d0ae69b9 100644
--- a/src/analyses/cfg_dominators.h
+++ b/src/analyses/cfg_dominators.h
@@ -224,6 +224,13 @@ void dominators_pretty_print_node(const T &node, std::ostream &out)
   out << node;
 }
 
+inline void dominators_pretty_print_node(
+  const goto_programt::targett& target,
+  std::ostream& out)
+{
+  out << target->code.pretty();
+}
+
 /*******************************************************************\
 
 Function: cfg_dominators_templatet::output
@@ -241,7 +248,7 @@ void cfg_dominators_templatet::output(std::ostream &out) const
 {
   for(const auto &node : cfg.entry_map)
   {
-    T n=node.first;
+    auto n=node.first;
 
     dominators_pretty_print_node(n, out);
     if(post_dom)
diff --git a/src/analyses/constant_propagator.cpp b/src/analyses/constant_propagator.cpp
index 1fe89a7b8f6..6735d558cc3 100644
--- a/src/analyses/constant_propagator.cpp
+++ b/src/analyses/constant_propagator.cpp
@@ -6,8 +6,6 @@ Author: Peter Schrammel
 
 \*******************************************************************/
 
-// #define DEBUG
-
 #ifdef DEBUG
 #include 
 #endif
@@ -20,6 +18,61 @@ Author: Peter Schrammel
 
 /*******************************************************************\
 
+Function: concatenate_array_id
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+exprt concatenate_array_id(
+		const exprt &array, const exprt &index,
+		const typet &type)
+{
+  std::string a, idx, identifier;
+  a = array.get_string(ID_identifier);
+
+  if (index.id()==ID_typecast)
+    idx = index.op0().get_string(ID_value);
+  else
+    idx = index.get_string(ID_value);
+
+  mp_integer i=string2integer(idx);
+  identifier=a+"["+integer2string(i)+"]";
+  symbol_exprt new_expr(identifier, type);
+
+  return new_expr;
+}
+
+/*******************************************************************\
+
+Function: concatenate_array_id
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+exprt concatenate_array_id(
+		const exprt &array, const mp_integer &index,
+		const typet &type)
+{
+  std::string a, identifier;
+  a = array.get_string(ID_identifier);
+  identifier=a+"["+integer2string(index)+"]";
+  symbol_exprt new_expr(identifier, type);
+
+  return new_expr;
+}
+
+/*******************************************************************\
+
 Function: constant_propagator_domaint::assign_rec
 
   Inputs:
@@ -35,14 +88,36 @@ void constant_propagator_domaint::assign_rec(
   const exprt &lhs, const exprt &rhs,
   const namespacet &ns)
 {
-  const typet &rhs_type = ns.follow(rhs.type());
+  const typet & lhs_type = ns.follow(lhs.type());
+  const typet & rhs_type = ns.follow(rhs.type());
 
 #ifdef DEBUG
   std::cout << "assign: " << from_expr(ns, "", lhs)
             << " := " << from_type(ns, "", rhs_type) << std::endl;
 #endif
 
-  if(lhs.id()==ID_symbol && rhs_type.id()!=ID_array
+  if(lhs.id()==ID_symbol && rhs.id()==ID_if)
+  {
+	exprt cond=rhs.op0();
+	assert(cond.operands().size()==2);
+	if(values.is_constant(cond.op0())
+			&& values.is_constant(cond.op1()))
+	{
+      if(cond.op0().id()==ID_index)
+      {
+    	exprt index=cond.op0();
+        exprt new_expr=concatenate_array_id(index.op0(), index.op1(), index.type());
+        values.replace_const(new_expr);
+        cond.op0()=new_expr;
+        cond = simplify_expr(cond,ns);
+      }
+      else
+        assert(0);
+
+      assign(values, to_symbol_expr(lhs), cond, ns);
+	}
+  }
+  else if(lhs.id()==ID_symbol && rhs_type.id()!=ID_array
                          && rhs_type.id()!=ID_struct
                          && rhs_type.id()!=ID_union)
   {
@@ -51,6 +126,27 @@ void constant_propagator_domaint::assign_rec(
     else
       values.set_to_top(to_symbol_expr(lhs));
   }
+  else if(lhs.id()==ID_symbol && lhs_type.id()==ID_array
+		                       && rhs_type.id()==ID_array)
+  {
+	exprt new_expr;
+	mp_integer idx=0;
+    forall_operands(it, rhs)
+	{
+  	  new_expr=concatenate_array_id(lhs, idx, it->type());
+  	  assign(values, to_symbol_expr(new_expr), *it, ns);
+  	  idx = idx +1;
+	}
+  }
+  else if (lhs.id()==ID_index)
+  {
+	if (values.is_constant(lhs.op1())
+	 && values.is_constant(rhs))
+	{
+	  exprt new_expr=concatenate_array_id(lhs.op0(), lhs.op1(), rhs.type());
+      assign(values, to_symbol_expr(new_expr), rhs, ns);
+	}
+  }
 #if 0
   else // TODO: could make field or array element-sensitive
   {
@@ -106,12 +202,22 @@ void constant_propagator_domaint::transform(
   else if(from->is_goto())
   {
     exprt g;
+
     if(from->get_target()==to)
       g = simplify_expr(from->guard, ns);
     else
       g = simplify_expr(not_exprt(from->guard), ns);
 
-    two_way_propagate_rec(g, ns);
+    if (g.is_false())
+     values.set_to_bottom();
+    else
+    {
+      //TODO: we need to support widening!
+      if (g.is_constant())
+        values.set_to_top();
+      else
+        two_way_propagate_rec(g, ns);
+    }
   }
   else if(from->is_dead())
   {
@@ -141,6 +247,7 @@ void constant_propagator_domaint::transform(
     else
       values.set_to_top();
   }
+
 #ifdef DEBUG
   std::cout << "after:\n";
   output(std::cout, ai, ns);
@@ -226,6 +333,30 @@ void constant_propagator_domaint::assign(
 
 /*******************************************************************\
 
+Function: constant_propagator_domaint::is_array_constant
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+bool constant_propagator_domaint::valuest::is_array_constant(const exprt &expr) const
+{
+  exprt new_expr = concatenate_array_id(expr.op0(),
+		  expr.op1(), expr.type());
+
+  if (replace_const.expr_map.find(to_symbol_expr(new_expr).get_identifier()) ==
+         replace_const.expr_map.end())
+    return false;
+
+  return true;
+}
+
+/*******************************************************************\
+
 Function: constant_propagator_domaint::valuest::is_constant
 
   Inputs:
@@ -251,6 +382,9 @@ bool constant_propagator_domaint::valuest::is_constant(const exprt &expr) const
        replace_const.expr_map.end())
       return false;
 
+  if (expr.id()==ID_index)
+	return is_array_constant(expr);
+
   if(expr.id()==ID_address_of)
     return is_constant_address_of(to_address_of_expr(expr).object());
 
@@ -401,38 +535,25 @@ bool constant_propagator_domaint::valuest::merge(const valuest &src)
       it!=replace_const.expr_map.end();
       ) // no it++
   {
-    if(src.replace_const.expr_map.find(it->first) ==
-       src.replace_const.expr_map.end())
+    const replace_symbolt::expr_mapt::const_iterator
+      b_it=src.replace_const.expr_map.find(it->first);
+
+    if(b_it==src.replace_const.expr_map.end())
     {
-      // cannot use set_to_top here
-      replace_const.expr_map.erase(it++);
+      //cannot use set_to_top here
+      replace_const.expr_map.erase(it);
       changed = true;
+      break;
     }
-    else ++it;
-  }
-
-  for(const auto &src_replace_pair : src.replace_const.expr_map)
-  {
-    replace_symbolt::expr_mapt::iterator c_it=
-      replace_const.expr_map.find(src_replace_pair.first);
-
-    if(c_it!=replace_const.expr_map.end())
+    else
     {
-      // values are different, set to top
-      if(c_it->second!=src_replace_pair.second)
-      {
-        changed=set_to_top(src_replace_pair.first);
-        assert(changed);
-      }
+      const exprt previous=it->second;
+      replace_const.expr_map[b_it->first]=b_it->second;
+      if (it->second != previous) changed = true;
+
+      it++;
     }
-    // is not in "this", ignore
-    else { }
   }
-
-#ifdef DEBUG
-  std::cout << "merged: " << changed << '\n';
-#endif
-
   return changed;
 }
 
@@ -521,6 +642,34 @@ void constant_propagator_ait::replace(
 
 /*******************************************************************\
 
+Function: constant_propagator_ait::replace_array_symbol
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+void constant_propagator_ait::replace_array_symbol(exprt &expr)
+{
+  if (expr.id()==ID_index)
+	expr = concatenate_array_id(expr.op0(),
+			  expr.op1(), expr.type());
+
+  Forall_operands(it, expr)
+  {
+	if (it->id()==ID_equal)
+	  replace_array_symbol(it->op0());
+	else if (it->id()==ID_index)
+	  replace_array_symbol(expr.op0());
+  }
+
+}
+
+/*******************************************************************\
+
 Function: constant_propagator_ait::replace
 
   Inputs:
@@ -547,6 +696,7 @@ void constant_propagator_ait::replace(
 
     if(it->is_goto() || it->is_assume() || it->is_assert())
     {
+      replace_array_symbol(it->guard);
       s_it->second.values.replace_const(it->guard);
       it->guard = simplify_expr(it->guard, ns);
     }
@@ -555,6 +705,8 @@ void constant_propagator_ait::replace(
       exprt &rhs = to_code_assign(it->code).rhs();
       s_it->second.values.replace_const(rhs);
       rhs = simplify_expr(rhs, ns);
+      if (rhs.id()==ID_constant)
+        rhs.add_source_location()=it->code.op0().source_location();
     }
     else if(it->is_function_call())
     {
diff --git a/src/analyses/constant_propagator.h b/src/analyses/constant_propagator.h
index 935b74a1421..0766b458f7d 100644
--- a/src/analyses/constant_propagator.h
+++ b/src/analyses/constant_propagator.h
@@ -62,6 +62,7 @@ class constant_propagator_domaint:public ai_domain_baset
     }
 
     bool is_constant(const exprt &expr) const;
+    bool is_array_constant(const exprt &expr) const;
     bool is_constant_address_of(const exprt &expr) const;
     bool set_to_top(const irep_idt &id);
 
@@ -75,6 +76,7 @@ class constant_propagator_domaint:public ai_domain_baset
       replace_const.clear();
       is_bottom = false;
     }
+
   };
 
   valuest values;
@@ -117,6 +119,11 @@ class constant_propagator_ait:public ait
   }
 
 protected:
+  friend class constant_propagator_domaint;
+
+  void replace_array_symbol(
+		  exprt &expr);
+
   void replace(
     goto_functionst::goto_functiont &,
     const namespacet &);
@@ -128,6 +135,7 @@ class constant_propagator_ait:public ait
   void replace_types_rec(
     const replace_symbolt &replace_const,
     exprt &expr);
+
 };
 
 #endif // CPROVER_ANALYSES_CONSTANT_PROPAGATOR_H
diff --git a/src/analyses/does_remove_const.cpp b/src/analyses/does_remove_const.cpp
new file mode 100644
index 00000000000..fcccd8219c9
--- /dev/null
+++ b/src/analyses/does_remove_const.cpp
@@ -0,0 +1,167 @@
+/*******************************************************************\
+
+ Module: Analyses
+
+ Author: DiffBlue Limited. All rights reserved.
+
+\*******************************************************************/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "does_remove_const.h"
+
+/*******************************************************************\
+
+Function: does_remove_constt::does_remove_constt
+
+  Inputs:
+   goto_program - the goto program to check
+   ns - the namespace of the goto program (used for checking type equality)
+
+ Outputs:
+
+ Purpose: A naive analysis to look for casts that remove const-ness from
+          pointers.
+
+\*******************************************************************/
+
+does_remove_constt::does_remove_constt(
+  const goto_programt &goto_program,
+  const namespacet &ns):
+    goto_program(goto_program),
+    ns(ns)
+{}
+
+/*******************************************************************\
+
+Function: does_remove_constt::operator()
+
+  Inputs:
+
+ Outputs: Returns true if the program contains a const-removing cast
+
+ Purpose: A naive analysis to look for casts that remove const-ness from
+          pointers.
+
+\*******************************************************************/
+
+bool does_remove_constt::operator()() const
+{
+  for(const goto_programt::instructiont &instruction :
+    goto_program.instructions)
+  {
+    if(!instruction.is_assign())
+    {
+      continue;
+    }
+
+    const code_assignt &assign=to_code_assign(instruction.code);
+    const typet &rhs_type=assign.rhs().type();
+    const typet &lhs_type=assign.lhs().type();
+
+    // Compare the types recursively for a point where the rhs is more
+    // const that the lhs
+    if(!is_type_at_least_as_const_as(&lhs_type, &rhs_type))
+    {
+      return true;
+    }
+
+    if(does_expr_lose_const(assign.rhs()))
+    {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+/*******************************************************************\
+
+Function: does_remove_constt::does_expr_lose_const()
+
+  Inputs:
+   expr - The expression to check
+
+ Outputs: Returns true if somewhere in the passed expression tree the const-ness
+          is lost.
+
+ Purpose: Search the expression tree to look for any children that have the
+          same base type, but a less strict const qualification.
+          If one is found, we return true.
+
+\*******************************************************************/
+
+bool does_remove_constt::does_expr_lose_const(const exprt &expr) const
+{
+  const typet &root_type=expr.type();
+
+  // Look in each child that has the same base type as the root
+  for(const exprt &op : expr.operands())
+  {
+    const typet &op_type=op.type();
+    if(base_type_eq(op_type, root_type, ns))
+    {
+      // Is this child more const-qualified than the root
+      if(!is_type_at_least_as_const_as(&root_type, &op_type))
+      {
+        return true;
+      }
+    }
+
+    // Recursively check the children of this child
+    if(does_expr_lose_const(op))
+    {
+      return true;
+    }
+  }
+  return false;
+}
+
+/*******************************************************************\
+
+Function: does_remove_constt::is_type_at_least_as_const_as
+
+  Inputs:
+   type_more_const - the type we are expecting to be at least as const qualified
+   type_compare - the type we are comparing against which may be less const
+                  qualified
+
+ Outputs: Returns true if type_more_const is at least as const as type_compare
+
+ Purpose: A recursive check to check the type_more_const is at least as const
+          as type compare.
+
+          type_more_const | type_compare || result
+          ----------------------------------------
+          const int *     | const int *  -> true
+          int *           | const int *  -> false
+          const int *     | int *        -> true
+          int *           | int * const  -> false
+
+\*******************************************************************/
+
+bool does_remove_constt::is_type_at_least_as_const_as(
+  const typet *type_more_const, const typet *type_compare) const
+{
+  while(type_compare->id()!=ID_nil && type_more_const->id()!=ID_nil)
+  {
+    const c_qualifierst rhs_qualifiers(*type_compare);
+    const c_qualifierst lhs_qualifiers(*type_more_const);
+    if(rhs_qualifiers.is_constant && !lhs_qualifiers.is_constant)
+    {
+      return false;
+    }
+
+    type_compare=&type_compare->subtype();
+    type_more_const=&type_more_const->subtype();
+  }
+
+  // Both the types should have the same number of subtypes
+  assert(type_compare->id()==ID_nil && type_more_const->id()==ID_nil);
+  return true;
+}
diff --git a/src/analyses/does_remove_const.h b/src/analyses/does_remove_const.h
new file mode 100644
index 00000000000..594682c7d50
--- /dev/null
+++ b/src/analyses/does_remove_const.h
@@ -0,0 +1,31 @@
+/*******************************************************************\
+
+ Module: Analyses
+
+ Author: DiffBlue Limited. All rights reserved.
+
+\*******************************************************************/
+#ifndef CPROVER_ANALYSES_DOES_REMOVE_CONST_H
+#define CPROVER_ANALYSES_DOES_REMOVE_CONST_H
+
+#include 
+
+class goto_programt;
+
+class does_remove_constt
+{
+public:
+  does_remove_constt(const goto_programt &goto_program, const namespacet &ns);
+  bool operator()() const;
+
+private:
+  bool does_expr_lose_const(const exprt &expr) const;
+
+  bool is_type_at_least_as_const_as(
+    const typet *type_more_const, const typet *type_compare) const;
+
+  const goto_programt &goto_program;
+  const namespacet &ns;
+};
+
+#endif // CPROVER_ANALYSES_DOES_REMOVE_CONST_H
diff --git a/src/analyses/goto_check.cpp b/src/analyses/goto_check.cpp
index 7bba83bd298..cc418d6aed9 100644
--- a/src/analyses/goto_check.cpp
+++ b/src/analyses/goto_check.cpp
@@ -62,17 +62,19 @@ class goto_checkt
 
   typedef goto_functionst::goto_functiont goto_functiont;
 
-  void goto_check(goto_functiont &goto_function);
-
-  irep_idt mode;
+  void goto_check(goto_functiont &goto_function, const irep_idt &mode);
 
 protected:
   const namespacet &ns;
   local_bitvector_analysist *local_bitvector_analysis;
   goto_programt::const_targett t;
 
-  void check_rec(const exprt &expr, guardt &guard, bool address);
-  void check(const exprt &expr);
+  void check_rec(
+    const exprt &expr,
+    guardt &guard,
+    bool address,
+    const irep_idt &mode);
+  void check(const exprt &expr, const irep_idt &mode);
 
   void bounds_check(const index_exprt &expr, const guardt &guard);
   void div_by_zero_check(const div_exprt &expr, const guardt &guard);
@@ -84,7 +86,8 @@ class goto_checkt
     const dereference_exprt &expr,
     const guardt &guard,
     const exprt &access_lb,
-    const exprt &access_ub);
+    const exprt &access_ub,
+    const irep_idt &mode);
   void integer_overflow_check(const exprt &expr, const guardt &guard);
   void conversion_check(const exprt &expr, const guardt &guard);
   void float_overflow_check(const exprt &expr, const guardt &guard);
@@ -993,9 +996,10 @@ void goto_checkt::pointer_validity_check(
   const dereference_exprt &expr,
   const guardt &guard,
   const exprt &access_lb,
-  const exprt &access_ub)
+  const exprt &access_ub,
+  const irep_idt &mode)
 {
-  if(!enable_pointer_check)
+  if(mode!=ID_java && !enable_pointer_check)
     return;
 
   const exprt &pointer=expr.op0();
@@ -1373,7 +1377,8 @@ Function: goto_checkt::check_rec
 void goto_checkt::check_rec(
   const exprt &expr,
   guardt &guard,
-  bool address)
+  bool address,
+  const irep_idt &mode)
 {
   // we don't look into quantifiers
   if(expr.id()==ID_exists || expr.id()==ID_forall)
@@ -1384,18 +1389,18 @@ void goto_checkt::check_rec(
     if(expr.id()==ID_dereference)
     {
       assert(expr.operands().size()==1);
-      check_rec(expr.op0(), guard, false);
+      check_rec(expr.op0(), guard, false, mode);
     }
     else if(expr.id()==ID_index)
     {
       assert(expr.operands().size()==2);
-      check_rec(expr.op0(), guard, true);
-      check_rec(expr.op1(), guard, false);
+      check_rec(expr.op0(), guard, true, mode);
+      check_rec(expr.op1(), guard, false, mode);
     }
     else
     {
       forall_operands(it, expr)
-        check_rec(*it, guard, true);
+        check_rec(*it, guard, true, mode);
     }
     return;
   }
@@ -1403,7 +1408,7 @@ void goto_checkt::check_rec(
   if(expr.id()==ID_address_of)
   {
     assert(expr.operands().size()==1);
-    check_rec(expr.op0(), guard, true);
+    check_rec(expr.op0(), guard, true, mode);
     return;
   }
   else if(expr.id()==ID_and || expr.id()==ID_or)
@@ -1420,7 +1425,7 @@ void goto_checkt::check_rec(
         throw "`"+expr.id_string()+"' takes Boolean operands only, but got "+
               op.pretty();
 
-      check_rec(op, guard, false);
+      check_rec(op, guard, false, mode);
 
       if(expr.id()==ID_or)
         guard.add(not_exprt(op));
@@ -1445,19 +1450,19 @@ void goto_checkt::check_rec(
       throw msg;
     }
 
-    check_rec(expr.op0(), guard, false);
+    check_rec(expr.op0(), guard, false, mode);
 
     {
       guardt old_guard=guard;
       guard.add(expr.op0());
-      check_rec(expr.op1(), guard, false);
+      check_rec(expr.op1(), guard, false, mode);
       guard.swap(old_guard);
     }
 
     {
       guardt old_guard=guard;
       guard.add(not_exprt(expr.op0()));
-      check_rec(expr.op2(), guard, false);
+      check_rec(expr.op2(), guard, false, mode);
       guard.swap(old_guard);
     }
 
@@ -1470,7 +1475,7 @@ void goto_checkt::check_rec(
     const dereference_exprt &deref=
       to_dereference_expr(member.struct_op());
 
-    check_rec(deref.op0(), guard, false);
+    check_rec(deref.op0(), guard, false, mode);
 
     exprt access_ub=nil_exprt();
 
@@ -1480,13 +1485,13 @@ void goto_checkt::check_rec(
     if(member_offset.is_not_nil() && size.is_not_nil())
       access_ub=plus_exprt(member_offset, size);
 
-    pointer_validity_check(deref, guard, member_offset, access_ub);
+    pointer_validity_check(deref, guard, member_offset, access_ub, mode);
 
     return;
   }
 
   forall_operands(it, expr)
-    check_rec(*it, guard, false);
+    check_rec(*it, guard, false, mode);
 
   if(expr.id()==ID_index)
   {
@@ -1545,7 +1550,8 @@ void goto_checkt::check_rec(
       to_dereference_expr(expr),
       guard,
       nil_exprt(),
-      size_of_expr(expr.type(), ns));
+      size_of_expr(expr.type(), ns),
+      mode);
 }
 
 /*******************************************************************\
@@ -1560,10 +1566,10 @@ Function: goto_checkt::check
 
 \*******************************************************************/
 
-void goto_checkt::check(const exprt &expr)
+void goto_checkt::check(const exprt &expr, const irep_idt &mode)
 {
   guardt guard;
-  check_rec(expr, guard, false);
+  check_rec(expr, guard, false, mode);
 }
 
 /*******************************************************************\
@@ -1574,18 +1580,14 @@ Function: goto_checkt::goto_check
 
  Outputs:
 
- Purpose:[B
+ Purpose:
 
 \*******************************************************************/
 
-void goto_checkt::goto_check(goto_functiont &goto_function)
+void goto_checkt::goto_check(
+  goto_functiont &goto_function,
+  const irep_idt &mode)
 {
-  {
-    const symbolt *init_symbol;
-    if(!ns.lookup(CPROVER_PREFIX "initialize", init_symbol))
-      mode=init_symbol->mode;
-  }
-
   assertions.clear();
 
   local_bitvector_analysist local_bitvector_analysis_obj(goto_function);
@@ -1607,7 +1609,7 @@ void goto_checkt::goto_check(goto_functiont &goto_function)
        i.is_target())
       assertions.clear();
 
-    check(i.guard);
+    check(i.guard, mode);
 
     // magic ERROR label?
     for(const auto &label : error_labels)
@@ -1633,20 +1635,20 @@ void goto_checkt::goto_check(goto_functiont &goto_function)
 
       if(statement==ID_expression)
       {
-        check(i.code);
+        check(i.code, mode);
       }
       else if(statement==ID_printf)
       {
         forall_operands(it, i.code)
-          check(*it);
+          check(*it, mode);
       }
     }
     else if(i.is_assign())
     {
       const code_assignt &code_assign=to_code_assign(i.code);
 
-      check(code_assign.lhs());
-      check(code_assign.rhs());
+      check(code_assign.lhs(), mode);
+      check(code_assign.rhs(), mode);
 
       // the LHS might invalidate any assertion
       invalidate(code_assign.lhs());
@@ -1686,7 +1688,7 @@ void goto_checkt::goto_check(goto_functiont &goto_function)
       }
 
       forall_operands(it, code_function_call)
-        check(*it);
+        check(*it, mode);
 
       // the call might invalidate any assertion
       assertions.clear();
@@ -1695,7 +1697,7 @@ void goto_checkt::goto_check(goto_functiont &goto_function)
     {
       if(i.code.operands().size()==1)
       {
-        check(i.code.op0());
+        check(i.code.op0(), mode);
         // the return value invalidate any assertion
         invalidate(i.code.op0());
       }
@@ -1853,7 +1855,7 @@ void goto_check(
   goto_functionst::goto_functiont &goto_function)
 {
   goto_checkt goto_check(ns, options);
-  goto_check.goto_check(goto_function);
+  goto_check.goto_check(goto_function, irep_idt());
 }
 
 /*******************************************************************\
@@ -1877,7 +1879,8 @@ void goto_check(
 
   Forall_goto_functions(it, goto_functions)
   {
-    goto_check.goto_check(it->second);
+    irep_idt mode=ns.lookup(it->first).mode;
+    goto_check.goto_check(it->second, mode);
   }
 }
 
@@ -1898,10 +1901,5 @@ void goto_check(
   goto_modelt &goto_model)
 {
   const namespacet ns(goto_model.symbol_table);
-  goto_checkt goto_check(ns, options);
-
-  Forall_goto_functions(it, goto_model.goto_functions)
-  {
-    goto_check.goto_check(it->second);
-  }
+  goto_check(ns, options, goto_model.goto_functions);
 }
diff --git a/src/analyses/goto_check.h b/src/analyses/goto_check.h
index 7ad04f99f79..4e1bbbbba60 100644
--- a/src/analyses/goto_check.h
+++ b/src/analyses/goto_check.h
@@ -37,7 +37,7 @@ void goto_check(
 
 #define HELP_GOTO_CHECK \
   " --bounds-check               enable array bounds checks\n" \
-  " --pointer-check              enable pointer checks\n" \
+  " --pointer-check              enable pointer checks (always enabled for Java)\n" /* NOLINT(whitespace/line_length) */ \
   " --memory-leak-check          enable memory leak checks\n" \
   " --div-by-zero-check          enable division by zero checks\n" \
   " --signed-overflow-check      enable signed arithmetic over- and underflow checks\n" /* NOLINT(whitespace/line_length) */ \
diff --git a/src/analyses/interval_domain.cpp b/src/analyses/interval_domain.cpp
index cc10fd89b00..1faf8c52364 100644
--- a/src/analyses/interval_domain.cpp
+++ b/src/analyses/interval_domain.cpp
@@ -157,7 +157,9 @@ bool interval_domaint::merge(
   for(int_mapt::iterator it=int_map.begin();
       it!=int_map.end(); ) // no it++
   {
-    const int_mapt::const_iterator b_it=b.int_map.begin();
+    //search for the variable that needs to be merged
+    //containers have different size and variable order
+    const int_mapt::const_iterator b_it=b.int_map.find(it->first);
     if(b_it==b.int_map.end())
     {
       it=int_map.erase(it);
diff --git a/src/analyses/is_threaded.h b/src/analyses/is_threaded.h
index ceb10494665..738857b8b8a 100644
--- a/src/analyses/is_threaded.h
+++ b/src/analyses/is_threaded.h
@@ -29,6 +29,11 @@ class is_threadedt
     return is_threaded_set.find(t)!=is_threaded_set.end();
   }
 
+  bool operator()(void) const
+  {
+    return !is_threaded_set.empty();
+  }
+
 protected:
   typedef std::set is_threaded_sett;
   is_threaded_sett is_threaded_set;
diff --git a/src/analyses/local_bitvector_analysis.cpp b/src/analyses/local_bitvector_analysis.cpp
index 43cb5c1d360..3fc0d10bb09 100644
--- a/src/analyses/local_bitvector_analysis.cpp
+++ b/src/analyses/local_bitvector_analysis.cpp
@@ -253,7 +253,9 @@ local_bitvector_analysist::flagst local_bitvector_analysist::get_rec(
   {
     if(rhs.operands().size()>=3)
     {
-      return get_rec(make_binary(rhs), loc_info_src);
+      assert(rhs.op0().type().id()==ID_pointer);
+      return get_rec(rhs.op0(), loc_info_src) |
+             flagst::mk_uses_offset();
     }
     else if(rhs.operands().size()==2)
     {
diff --git a/src/analyses/local_may_alias.cpp b/src/analyses/local_may_alias.cpp
index 53d089b9544..ffaefe73667 100644
--- a/src/analyses/local_may_alias.cpp
+++ b/src/analyses/local_may_alias.cpp
@@ -12,7 +12,6 @@ Author: Daniel Kroening, kroening@kroening.com
 #include 
 #include 
 #include 
-#include 
 
 #include 
 #include 
@@ -309,7 +308,8 @@ void local_may_aliast::get_rec(
   {
     if(rhs.operands().size()>=3)
     {
-      get_rec(dest, make_binary(rhs), loc_info_src);
+      assert(rhs.op0().type().id()==ID_pointer);
+      get_rec(dest, rhs.op0(), loc_info_src);
     }
     else if(rhs.operands().size()==2)
     {
diff --git a/src/analyses/natural_loops.cpp b/src/analyses/natural_loops.cpp
index 16985daa5e9..593fc78006d 100644
--- a/src/analyses/natural_loops.cpp
+++ b/src/analyses/natural_loops.cpp
@@ -10,8 +10,6 @@ Author: Georg Weissenbacher, georg@weissenbacher.name
 
 #include "natural_loops.h"
 
-// #define DEBUG
-
 /*******************************************************************\
 
 Function: show_natural_loops
diff --git a/src/analyses/natural_loops.h b/src/analyses/natural_loops.h
index 327ebbdf112..ff56c687c93 100644
--- a/src/analyses/natural_loops.h
+++ b/src/analyses/natural_loops.h
@@ -81,8 +81,6 @@ Function: natural_loops_templatet::compute
 
 \*******************************************************************/
 
-// #define DEBUG
-
 #ifdef DEBUG
 #include 
 #endif
diff --git a/src/analyses/reaching_definitions.h b/src/analyses/reaching_definitions.h
index 2ef4a549040..a48a271a9a6 100644
--- a/src/analyses/reaching_definitions.h
+++ b/src/analyses/reaching_definitions.h
@@ -160,7 +160,7 @@ class rd_range_domaint:public ai_domain_baset
   typedef std::map ranges_at_loct;
 
   const ranges_at_loct &get(const irep_idt &identifier) const;
-  const void clear_cache(const irep_idt &identifier) const
+  void clear_cache(const irep_idt &identifier) const
   {
     export_cache[identifier].clear();
   }
diff --git a/src/ansi-c/ansi_c_declaration.cpp b/src/ansi-c/ansi_c_declaration.cpp
index 4c82adc307a..7f9d0980583 100644
--- a/src/ansi-c/ansi_c_declaration.cpp
+++ b/src/ansi-c/ansi_c_declaration.cpp
@@ -146,6 +146,10 @@ typet ansi_c_declarationt::full_type(
 
   *p=type();
 
+  // retain typedef for dump-c
+  if(get_is_typedef())
+    result.set(ID_C_typedef, declarator.get_name());
+
   return result;
 }
 
diff --git a/src/ansi-c/c_typecheck_type.cpp b/src/ansi-c/c_typecheck_type.cpp
index f875bdec7d4..d82e81c0038 100644
--- a/src/ansi-c/c_typecheck_type.cpp
+++ b/src/ansi-c/c_typecheck_type.cpp
@@ -52,6 +52,7 @@ void c_typecheck_baset::typecheck_type(typet &type)
     c_qualifiers+=c_qualifierst(type.subtype());
     bool packed=type.get_bool(ID_C_packed);
     exprt alignment=static_cast(type.find(ID_C_alignment));
+    irept _typedef=type.find(ID_C_typedef);
 
     type.swap(type.subtype());
 
@@ -60,6 +61,8 @@ void c_typecheck_baset::typecheck_type(typet &type)
       type.set(ID_C_packed, true);
     if(alignment.is_not_nil())
       type.add(ID_C_alignment, alignment);
+    if(_typedef.is_not_nil())
+      type.add(ID_C_typedef, _typedef);
 
     return; // done
   }
diff --git a/src/ansi-c/expr2c.cpp b/src/ansi-c/expr2c.cpp
index b0143b66912..b35b5010608 100644
--- a/src/ansi-c/expr2c.cpp
+++ b/src/ansi-c/expr2c.cpp
@@ -232,6 +232,11 @@ std::string expr2ct::convert_rec(
   std::string d=
     declarator==""?declarator:" "+declarator;
 
+  if(src.find(ID_C_typedef).is_not_nil())
+  {
+    return q+id2string(src.get(ID_C_typedef))+d;
+  }
+
   if(src.id()==ID_bool)
   {
     return q+"_Bool"+d;
diff --git a/src/big-int/bigint-test.cc b/src/big-int/bigint-test.cc
index 6c8b9c84b64..5d506a89013 100644
--- a/src/big-int/bigint-test.cc
+++ b/src/big-int/bigint-test.cc
@@ -298,7 +298,7 @@ run_floorPow2_tests ()
 
   for (unsigned i = 0; i < 512; ++i) {
     unsigned x = 512 - i;
-    N = pow(2,x);
+    N = pow(BigInt(2),x);
     M.setPower2(x);
 
     if (!(N == M)) {
@@ -327,7 +327,7 @@ run_floorPow2_tests ()
 
   }
 
-  N = pow(2,0);  // 1
+  N = pow(BigInt(2),0);  // 1
   M.setPower2(0);
 
   if (!(N == M)) {
diff --git a/src/cbmc/bmc.cpp b/src/cbmc/bmc.cpp
index 2f39d97b1ce..f1e005a46a1 100644
--- a/src/cbmc/bmc.cpp
+++ b/src/cbmc/bmc.cpp
@@ -687,7 +687,7 @@ void bmct::setup_unwind()
 
   for(auto &val : unwindset_loops)
   {
-    unsigned thread_nr;
+    unsigned thread_nr=0;
     bool thread_nr_set=false;
 
     if(!val.empty() &&
diff --git a/src/cbmc/cbmc_parse_options.cpp b/src/cbmc/cbmc_parse_options.cpp
index 5af90c00b79..1619143ce6c 100644
--- a/src/cbmc/cbmc_parse_options.cpp
+++ b/src/cbmc/cbmc_parse_options.cpp
@@ -883,8 +883,6 @@ bool cbmc_parse_optionst::process_goto_program(
     remove_asm(symbol_table, goto_functions);
 
     // add the library
-    status() << "Adding CPROVER library ("
-             << config.ansi_c.arch << ")" << eom;
     link_to_library(symbol_table, goto_functions, ui_message_handler);
 
     if(cmdline.isset("string-abstraction"))
@@ -894,6 +892,7 @@ bool cbmc_parse_optionst::process_goto_program(
     // remove function pointers
     status() << "Removal of function pointers and virtual functions" << eom;
     remove_function_pointers(
+      get_message_handler(),
       symbol_table,
       goto_functions,
       cmdline.isset("pointer-check"));
@@ -967,7 +966,7 @@ bool cbmc_parse_optionst::process_goto_program(
     if(cmdline.isset("drop-unused-functions"))
     {
       // Entry point will have been set before and function pointers removed
-      status() << "Removing Unused Functions" << eom;
+      status() << "Removing unused functions" << eom;
       remove_unused_functions(goto_functions, ui_message_handler);
     }
 
@@ -1117,7 +1116,6 @@ void cbmc_parse_optionst::help()
     " --property id                only check one specific property\n"
     " --stop-on-fail               stop analysis once a failed property is detected\n" // NOLINT(*)
     " --trace                      give a counterexample trace for failed properties\n" //NOLINT(*)
-    " --drop-unused-functions      drop functions trivially unreachable from main function\n" // NOLINT(*)
     "\n"
     "C/C++ frontend options:\n"
     " -I path                      set include path (C/C++)\n"
@@ -1163,6 +1161,7 @@ void cbmc_parse_optionst::help()
     " --show-parse-tree            show parse tree\n"
     " --show-symbol-table          show symbol table\n"
     HELP_SHOW_GOTO_FUNCTIONS
+    " --drop-unused-functions      drop functions trivially unreachable from main function\n" // NOLINT(*)
     "\n"
     "Program instrumentation options:\n"
     HELP_GOTO_CHECK
@@ -1224,5 +1223,6 @@ void cbmc_parse_optionst::help()
     " --xml-ui                     use XML-formatted output\n"
     " --xml-interface              bi-directional XML interface\n"
     " --json-ui                    use JSON-formatted output\n"
+    " --verbosity #                verbosity level\n"
     "\n";
 }
diff --git a/src/cbmc/symex_bmc.cpp b/src/cbmc/symex_bmc.cpp
index 1dd1e8dceb9..5ae65275ef6 100644
--- a/src/cbmc/symex_bmc.cpp
+++ b/src/cbmc/symex_bmc.cpp
@@ -9,6 +9,7 @@ Author: Daniel Kroening, kroening@kroening.com
 #include 
 
 #include 
+#include 
 
 #include "symex_bmc.h"
 
@@ -63,11 +64,67 @@ void symex_bmct::symex_step(
     last_source_location=source_location;
   }
 
-  if(record_coverage &&
-     !state.guard.is_false())
-    symex_coverage.covered(state.source.pc);
+  const goto_programt::const_targett cur_pc=state.source.pc;
+
+  if(!state.guard.is_false() &&
+     state.source.pc->is_assume() &&
+     simplify_expr(state.source.pc->guard, ns).is_false())
+  {
+    statistics() << "aborting path on assume(false) at "
+                 << state.source.pc->source_location
+                 << " thread " << state.source.thread_nr;
+
+    const irep_idt &c=state.source.pc->source_location.get_comment();
+    if(!c.empty())
+      statistics() << ": " << c;
+
+    statistics() << eom;
+  }
 
   goto_symext::symex_step(goto_functions, state);
+
+  if(record_coverage &&
+     // is the instruction being executed
+     !state.guard.is_false() &&
+     // avoid an invalid iterator in state.source.pc
+     (!cur_pc->is_end_function() ||
+      cur_pc->function!=goto_functions.entry_point()) &&
+     // ignore transition to next instruction when goto points elsewhere
+     (!cur_pc->is_goto() ||
+      cur_pc->get_target()==state.source.pc ||
+      !cur_pc->guard.is_true()))
+    symex_coverage.covered(cur_pc, state.source.pc);
+}
+
+/*******************************************************************\
+
+Function: symex_bmct::merge_goto
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+void symex_bmct::merge_goto(
+  const statet::goto_statet &goto_state,
+  statet &state)
+{
+  const goto_programt::const_targett prev_pc=goto_state.source.pc;
+  const guardt prev_guard=goto_state.guard;
+
+  goto_symext::merge_goto(goto_state, state);
+
+  assert(prev_pc->is_goto());
+  if(record_coverage &&
+     // could the branch possibly be taken?
+     !prev_guard.is_false() &&
+     !state.guard.is_false() &&
+     // branches only, no single-successor goto
+     !prev_pc->guard.is_true())
+    symex_coverage.covered(prev_pc, state.source.pc);
 }
 
 /*******************************************************************\
diff --git a/src/cbmc/symex_bmc.h b/src/cbmc/symex_bmc.h
index 10f4b821e88..8b2df348f3b 100644
--- a/src/cbmc/symex_bmc.h
+++ b/src/cbmc/symex_bmc.h
@@ -83,6 +83,10 @@ class symex_bmct:
     const goto_functionst &goto_functions,
     statet &state);
 
+  virtual void merge_goto(
+    const statet::goto_statet &goto_state,
+    statet &state);
+
   // for loop unwinding
   virtual bool get_unwind(
     const symex_targett::sourcet &source,
diff --git a/src/cbmc/symex_coverage.cpp b/src/cbmc/symex_coverage.cpp
index 69af02e9e9e..812df4de062 100644
--- a/src/cbmc/symex_coverage.cpp
+++ b/src/cbmc/symex_coverage.cpp
@@ -19,6 +19,7 @@ Date: March 2016
 #include 
 
 #include 
+#include 
 
 #include "symex_coverage.h"
 
@@ -57,26 +58,37 @@ class goto_program_coverage_recordt:public coverage_recordt
 protected:
   irep_idt file_name;
 
-  struct line_coverage_recordt
+  struct coverage_conditiont
   {
-    line_coverage_recordt():
-      hits(0), is_branch(false), branch_covered(false)
+    coverage_conditiont():
+      false_taken(false), true_taken(false)
+    {
+    }
+
+    bool false_taken;
+    bool true_taken;
+  };
+
+  struct coverage_linet
+  {
+    coverage_linet():
+      hits(0)
     {
     }
 
     unsigned hits;
-    bool is_branch;
-    bool branch_covered;
+    std::map
+      conditions;
   };
 
-  typedef std::map
-    line_coverage_mapt;
+  typedef std::map
+    coverage_lines_mapt;
 
-  void compute_line_coverage(
+  void compute_coverage_lines(
     const goto_programt &goto_program,
     const irep_idt &file_name,
     const symex_coveraget::coveraget &coverage,
-    line_coverage_mapt &dest);
+    coverage_lines_mapt &dest);
 };
 
 /*******************************************************************\
@@ -91,17 +103,26 @@ Function: rate
 
 \*******************************************************************/
 
-static std::string rate(std::size_t covered, std::size_t total)
+static std::string rate(
+  std::size_t covered,
+  std::size_t total,
+  bool per_cent=false)
 {
+  std::ostringstream oss;
+
 #if 1
-  if(total==0)
-    return "1.0";
+  float fraction;
 
-  std::ostringstream oss;
+  if(total==0)
+    fraction=1.0;
+  else
+    fraction=static_cast(covered)/static_cast(total);
 
-  oss << static_cast(covered)/static_cast(total);
+  if(per_cent)
+    oss << fraction*100.0 << '%';
+  else
+    oss << fraction;
 #else
-  std::ostringstream oss;
   oss << covered << " of " << total;
 #endif
 
@@ -137,12 +158,12 @@ goto_program_coverage_recordt::goto_program_coverage_recordt(
   assert(!file_name.empty());
 
   // compute the maximum coverage of individual source-code lines
-  line_coverage_mapt line_coverage_map;
-  compute_line_coverage(
+  coverage_lines_mapt coverage_lines_map;
+  compute_coverage_lines(
     gf_it->second.body,
     file_name,
     coverage,
-    line_coverage_map);
+    coverage_lines_map);
 
   // 
   //   
@@ -157,8 +178,14 @@ goto_program_coverage_recordt::goto_program_coverage_recordt(
   //   
   // 
   xml.set_attribute("name", id2string(gf_it->first));
+
+  code_typet sig_type=
+    original_return_type(ns.get_symbol_table(), gf_it->first);
+  if(sig_type.is_nil())
+    sig_type=gf_it->second.type;
   xml.set_attribute("signature",
-                    from_type(ns, gf_it->first, gf_it->second.type));
+                    from_type(ns, gf_it->first, sig_type));
+
   xml.set_attribute("line-rate",
                     rate(lines_covered, lines_total));
   xml.set_attribute("branch-rate",
@@ -166,28 +193,43 @@ goto_program_coverage_recordt::goto_program_coverage_recordt(
 
   xmlt &lines=xml.new_element("lines");
 
-  for(line_coverage_mapt::const_iterator
-      it=line_coverage_map.begin();
-      it!=line_coverage_map.end();
-      ++it)
+  for(const auto &cov_line : coverage_lines_map)
   {
     xmlt &line=lines.new_element("line");
 
-    line.set_attribute("number", std::to_string(it->first));
-    line.set_attribute("hits", std::to_string(it->second.hits));
-    if(!it->second.is_branch)
+    line.set_attribute("number", std::to_string(cov_line.first));
+    line.set_attribute("hits", std::to_string(cov_line.second.hits));
+    if(cov_line.second.conditions.empty())
       line.set_attribute("branch", "false");
     else
     {
-      // TODO: conditions
       line.set_attribute("branch", "true");
+
+      xmlt &conditions=line.new_element("conditions");
+
+      std::size_t number=0, total_taken=0;
+      for(const auto &c : cov_line.second.conditions)
+      {
+        // 
+        xmlt &condition=conditions.new_element("condition");
+        condition.set_attribute("number", std::to_string(number++));
+        condition.set_attribute("type", "jump");
+        unsigned taken=c.second.false_taken+c.second.true_taken;
+        total_taken+=taken;
+        condition.set_attribute("coverage", rate(taken, 2, true));
+      }
+
+      std::ostringstream oss;
+      oss << rate(total_taken, number*2, true)
+          << " (" << total_taken << '/' << number*2 << ')';
+      line.set_attribute("condition-coverage", oss.str());
     }
   }
 }
 
 /*******************************************************************\
 
-Function: goto_program_coverage_recordt::compute_line_coverage
+Function: goto_program_coverage_recordt::compute_coverage_lines
 
   Inputs:
 
@@ -197,58 +239,83 @@ Function: goto_program_coverage_recordt::compute_line_coverage
 
 \*******************************************************************/
 
-void goto_program_coverage_recordt::compute_line_coverage(
+void goto_program_coverage_recordt::compute_coverage_lines(
     const goto_programt &goto_program,
     const irep_idt &file_name,
     const symex_coveraget::coveraget &coverage,
-    line_coverage_mapt &dest)
+    coverage_lines_mapt &dest)
 {
   forall_goto_program_instructions(it, goto_program)
   {
     if(it->source_location.is_nil() ||
-       it->source_location.get_file()!=file_name)
+       it->source_location.get_file()!=file_name ||
+       it->is_dead() ||
+       it->is_end_function())
       continue;
 
     const bool is_branch=it->is_goto() && !it->guard.is_constant();
 
     unsigned l=
       safe_string2unsigned(id2string(it->source_location.get_line()));
-    std::pair entry=
-      dest.insert(std::make_pair(l, line_coverage_recordt()));
+    std::pair entry=
+      dest.insert(std::make_pair(l, coverage_linet()));
 
     if(entry.second)
-    {
       ++lines_total;
-      if(is_branch)
-        ++branches_total;
-    }
 
     // mark as branch if any instruction in this source code line is
     // a branching instruction
-    if(is_branch &&
-       !entry.first->second.is_branch)
+    if(is_branch)
     {
-      ++branches_total;
-      entry.first->second.is_branch=true;
+      branches_total+=2;
+      if(!entry.first->second.conditions.insert(
+          {it, coverage_conditiont()}).second)
+        assert(false);
     }
 
     symex_coveraget::coveraget::const_iterator c_entry=
       coverage.find(it);
-    if(c_entry!=coverage.end() &&
-       c_entry->second.num_executions>0)
+    if(c_entry!=coverage.end())
     {
-      // maximum over all instructions in this source code line
-      if(c_entry->second.num_executions>entry.first->second.hits)
+      if(!(c_entry->second.size()==1 || is_branch))
       {
-        if(entry.first->second.hits==0)
-          ++lines_covered;
-        entry.first->second.hits=c_entry->second.num_executions;
+        std::cerr << it->location_number << std::endl;
+        for(const auto &cov : c_entry->second)
+          std::cerr << cov.second.succ->location_number << std::endl;
       }
+      assert(c_entry->second.size()==1 || is_branch);
 
-      if(is_branch && !entry.first->second.branch_covered)
+      for(const auto &cov : c_entry->second)
       {
-        ++branches_covered;
-        entry.first->second.branch_covered=true;
+        assert(cov.second.num_executions>0);
+
+        if(entry.first->second.hits==0)
+          ++lines_covered;
+
+        entry.first->second.hits+=cov.second.num_executions;
+
+        if(is_branch)
+        {
+          auto cond_entry=entry.first->second.conditions.find(it);
+          assert(cond_entry!=entry.first->second.conditions.end());
+
+          if(it->get_target()==cov.second.succ)
+          {
+            if(!cond_entry->second.false_taken)
+            {
+              cond_entry->second.false_taken=true;
+              ++branches_covered;
+            }
+          }
+          else
+          {
+            if(!cond_entry->second.true_taken)
+            {
+              cond_entry->second.true_taken=true;
+              ++branches_covered;
+            }
+          }
+        }
       }
     }
   }
@@ -276,7 +343,7 @@ void symex_coveraget::compute_overall_coverage(
   forall_goto_functions(gf_it, goto_functions)
   {
     if(!gf_it->second.body_available() ||
-       gf_it->first==ID__start ||
+       gf_it->first==goto_functions.entry_point() ||
        gf_it->first==CPROVER_PREFIX "initialize")
       continue;
 
diff --git a/src/cbmc/symex_coverage.h b/src/cbmc/symex_coverage.h
index 0e71b430630..c173bc65ad7 100644
--- a/src/cbmc/symex_coverage.h
+++ b/src/cbmc/symex_coverage.h
@@ -29,11 +29,12 @@ class symex_coveraget
   {
   }
 
-  void covered(goto_programt::const_targett location)
+  void covered(
+    goto_programt::const_targett from,
+    goto_programt::const_targett to)
   {
-    std::pair entry=
-      coverage.insert(std::make_pair(location,
-                                     coverage_infot(location, 1)));
+    std::pair entry=
+      coverage[from].insert({to, coverage_infot(from, to, 1)});
 
     if(!entry.second)
       ++(entry.first->second.num_executions);
@@ -49,17 +50,22 @@ class symex_coveraget
   struct coverage_infot
   {
     coverage_infot(
-      goto_programt::const_targett _location,
+      goto_programt::const_targett _from,
+      goto_programt::const_targett _to,
       unsigned _num_executions):
-      location(_location), num_executions(_num_executions)
+      location(_from), num_executions(_num_executions),
+      succ(_to)
     {
     }
 
     goto_programt::const_targett location;
     unsigned num_executions;
+    goto_programt::const_targett succ;
   };
 
   typedef std::map
+    coverage_innert;
+  typedef std::map
     coveraget;
   coveraget coverage;
 
diff --git a/src/cegis/invariant/fitness/concrete_fitness_source_provider.cpp b/src/cegis/invariant/fitness/concrete_fitness_source_provider.cpp
index 28e41138cb3..dbfa21257c5 100644
--- a/src/cegis/invariant/fitness/concrete_fitness_source_provider.cpp
+++ b/src/cegis/invariant/fitness/concrete_fitness_source_provider.cpp
@@ -69,9 +69,15 @@ bool contains(const std::string &haystack, const std::string &needle)
   return std::string::npos != haystack.find(needle);
 }
 
-bool handle_start(std::string &source, const std::string &line)
+bool handle_start(
+  const goto_functionst &gf,
+  std::string &source,
+  const std::string &line)
 {
-  if ("void _start(void)" != line) return false;
+  std::ostringstream start_sig;
+  start_sig << "void " << gf.entry_point() << "(void)";
+  if(start_sig.str()!=line)
+    return false;
   source+="int main(const int argc, const char * const argv[])\n";
   return true;
 }
@@ -212,17 +218,24 @@ bool handle_internals(const std::string &line)
       || "static signed int assert#return_value;" == line;
 }
 
-void post_process(std::string &source, std::stringstream &ss)
+void post_process(
+  const goto_functionst &gf,
+  std::string &source,
+  std::stringstream &ss)
 {
   bool deserialise_initialised=false;
   bool ce_initialised=false;
   for (std::string line; std::getline(ss, line);)
   {
-    if (handle_start(source, line) || handle_return_value(line)
-        || handle_ce_loop(line, ss) || handle_internals(line)
-        || handle_programs(source, deserialise_initialised, line)
-        || handle_x0(source, line) || handle_ce(source, ce_initialised, line)
-        || handle_second_instr_struct(source, line)) continue;
+    if(handle_start(gf, source, line) ||
+       handle_return_value(line) ||
+       handle_ce_loop(line, ss) ||
+       handle_internals(line) ||
+       handle_programs(source, deserialise_initialised, line) ||
+       handle_x0(source, line) ||
+       handle_ce(source, ce_initialised, line) ||
+       handle_second_instr_struct(source, line))
+      continue;
     replace_ce_index(line);
     replace_assume(line);
     fix_cprover_names(line);
@@ -254,7 +267,7 @@ std::string &post_process_fitness_source(std::string &result,
   add_first_prog_offset(result, num_ce_vars);
   add_assume_implementation(result);
   add_danger_execute(result, num_vars, num_consts, max_prog_size, exec);
-  post_process(result, ss);
+  post_process(gf, result, ss);
   transform_program_individual_main_to_lib(result, danger);
   return result;
 }
diff --git a/src/cegis/jsa/genetic/jsa_source_provider.cpp b/src/cegis/jsa/genetic/jsa_source_provider.cpp
index 4984bfe1c9b..1182317f771 100644
--- a/src/cegis/jsa/genetic/jsa_source_provider.cpp
+++ b/src/cegis/jsa/genetic/jsa_source_provider.cpp
@@ -26,7 +26,6 @@ jsa_source_providert::jsa_source_providert(jsa_symex_learnt &lcfg) :
 {
 }
 
-#define START_METHOD_PREFIX "void _start"
 #define RETURN_VALUE_ASSIGNMENT RETURN_VALUE_SUFFIX" ="
 #define JUMP_BUFFER "__CPROVER_jsa_jump_buffer"
 #define TEST_SIGNATURE "int " CEGIS_FITNESS_TEST_FUNC \
@@ -104,7 +103,9 @@ void add_main_body(std::string &result, const jsa_symex_learnt &lcfg)
   std::ostringstream oss;
   dump_c(entry_only, false, ns, oss);
   const std::string main_body(oss.str());
-  result+=main_body.substr(main_body.find(START_METHOD_PREFIX));
+  result+=
+    main_body.substr(
+      main_body.find(std::string("void ")+id2string(gf.entry_point())));
 }
 
 void fix_return_values(std::string &result)
@@ -138,9 +139,11 @@ void fix_return_values(std::string &result)
   substitute(result, "\n  return 0;", "");
 }
 
-void add_facade_function(std::string &result)
+void add_facade_function(const goto_functionst &gf, std::string &result)
 {
-  substitute(result, "void _start(void)", TEST_SIGNATURE);
+  std::ostringstream start_sig;
+  start_sig << "void " << gf.entry_point() << "(void)";
+  substitute(result, start_sig.str(), TEST_SIGNATURE);
   const std::string::size_type pos=result.find("  __CPROVER_initialize();");
   result.insert(pos, "  if (setjmp(" JUMP_BUFFER")) return EXIT_FAILURE;\n");
 }
@@ -249,7 +252,7 @@ const std::string &jsa_source_providert::operator ()()
   add_temp_clean(source, lcfg.get_symbol_table());
   add_main_body(source, lcfg);
   fix_return_values(source);
-  add_facade_function(source);
+  add_facade_function(lcfg.get_goto_functions(), source);
   insert_solution(source, lcfg);
   insert_counterexample(source);
   cleanup(source);
diff --git a/src/clobber/clobber_parse_options.cpp b/src/clobber/clobber_parse_options.cpp
index 4ac42666639..803ab9db5b1 100644
--- a/src/clobber/clobber_parse_options.cpp
+++ b/src/clobber/clobber_parse_options.cpp
@@ -368,7 +368,6 @@ bool clobber_parse_optionst::get_goto_program(
 
     // finally add the library
     #if 0
-    status() << "Adding CPROVER library" << eom;
     link_to_library(symbol_table, goto_functions, ui_message_handler);
     #endif
 
diff --git a/src/cpp/cpp_typecheck.h b/src/cpp/cpp_typecheck.h
index 9c26ebbe16f..55955cd0334 100644
--- a/src/cpp/cpp_typecheck.h
+++ b/src/cpp/cpp_typecheck.h
@@ -136,13 +136,6 @@ class cpp_typecheckt:public c_typecheck_baset
     const template_typet &old_type,
     template_typet &new_type);
 
-  #if 0
-  void check_template_restrictions(
-    const irept &cpp_name,
-    const irep_idt &final_identifier,
-    const typet &final_type);
-  #endif
-
   void convert_template_declaration(cpp_declarationt &declaration);
 
   void convert_non_template_declaration(cpp_declarationt &declaration);
diff --git a/src/cpp/cpp_typecheck_template.cpp b/src/cpp/cpp_typecheck_template.cpp
index 002cdb51f69..79c609a0a4b 100644
--- a/src/cpp/cpp_typecheck_template.cpp
+++ b/src/cpp/cpp_typecheck_template.cpp
@@ -48,41 +48,6 @@ void cpp_typecheckt::salvage_default_arguments(
   }
 }
 
-#if 0
-/*******************************************************************\
-
-Function: cpp_typecheckt::check_template_restrictions
-
-  Inputs:
-
- Outputs:
-
- Purpose:
-
-\*******************************************************************/
-
-void cpp_typecheckt::check_template_restrictions(
-  const irept &cpp_name,
-  const irep_idt &final_identifier,
-  const typet &final_type)
-{
-  if(final_type.id()==ID_template)
-  {
-    // subtype must be class or function
-
-    if(final_type.subtype().id()!=ID_struct &&
-       final_type.subtype().id()!=ID_code)
-    {
-      error().source_location=cpp_name.location();
-      error() << "template only allowed with classes or functions,"
-              << " but got `" << to_string(final_type.subtype())
-              << "'" << eom;
-      throw 0;
-    }
-  }
-}
-#endif
-
 /*******************************************************************\
 
 Function: cpp_typecheckt::typecheck_class_template
diff --git a/src/cpp/parse.cpp b/src/cpp/parse.cpp
index 5a7d2095a58..b16340c3eef 100644
--- a/src/cpp/parse.cpp
+++ b/src/cpp/parse.cpp
@@ -21,8 +21,6 @@ Author: Daniel Kroening, kroening@cs.cmu.edu
 #include "cpp_member_spec.h"
 #include "cpp_enum_type.h"
 
-// #define DEBUG
-
 #ifdef DEBUG
 #include 
 
@@ -642,7 +640,7 @@ bool Parser::rDefinition(cpp_itemt &item)
   #ifdef DEBUG
   indenter _i;
   std::cout << std::string(__indent, ' ') << "Parser::rDefinition 1 " << t
-            << "\n";
+            << '\n';
   #endif
 
   if(t==';')
@@ -1238,11 +1236,11 @@ bool Parser::rTemplateDecl(cpp_declarationt &decl)
   {
   case tdk_decl:
     #ifdef DEBUG
-    std::cout << std::string(__indent, ' ') << "BODY: " << body << std::endl;
+    std::cout << std::string(__indent, ' ') << "BODY: "
+              << body.pretty() << '\n';
     std::cout << std::string(__indent, ' ') << "TEMPLATE_TYPE: "
-              << template_type << std::endl;
+              << template_type.pretty() << '\n';
     #endif
-
     body.add(ID_template_type).swap(template_type);
     body.set(ID_is_template, true);
     decl.swap(body);
@@ -1912,9 +1910,8 @@ bool Parser::rIntegralDeclaration(
       #ifdef DEBUG
       std::cout << std::string(__indent, ' ')
                 << "Parser::rIntegralDeclaration 8 "
-                << declaration << "\n";
+                << declaration.pretty() << '\n';
       #endif
-
       lex.get_token(tk);
       return true;
     }
@@ -5118,10 +5115,9 @@ bool Parser::rClassBody(exprt &body)
       // body=Ptree::List(ob, nil, new Leaf(tk));
       return true;        // error recovery
     }
-
     #ifdef DEBUG
-    std::cout << std::string(__indent, ' ') << "Parser::rClassBody " << member
-              << std::endl;
+    std::cout << std::string(__indent, ' ') << "Parser::rClassBody "
+              << member.pretty() << '\n';
     #endif
 
     members.move_to_operands(
@@ -7583,7 +7579,7 @@ bool Parser::rPrimaryExpr(exprt &exp)
   #ifdef DEBUG
   indenter _i;
   std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 0 "
-            << lex.LookAhead(0) << " " << lex.current_token().text <<"\n";
+            << lex.LookAhead(0) << ' ' << lex.current_token().text << '\n';
   #endif
 
   switch(lex.LookAhead(0))
@@ -9245,8 +9241,8 @@ bool Parser::rExprStatement(codet &statement)
     if(rDeclarationStatement(statement))
     {
       #ifdef DEBUG
-      std::cout << std::string(__indent, ' ') << "rDe: " << statement
-                << std::endl;
+      std::cout << std::string(__indent, ' ') << "rDe "
+                << statement.pretty() << '\n';
       #endif
       return true;
     }
diff --git a/src/goto-analyzer/goto_analyzer_parse_options.cpp b/src/goto-analyzer/goto_analyzer_parse_options.cpp
index e462740c1cc..5f889ff99d7 100644
--- a/src/goto-analyzer/goto_analyzer_parse_options.cpp
+++ b/src/goto-analyzer/goto_analyzer_parse_options.cpp
@@ -216,7 +216,7 @@ int goto_analyzer_parse_optionst::doit()
 
   goto_model.set_message_handler(get_message_handler());
 
-  if(goto_model(cmdline.args))
+  if(goto_model(cmdline))
     return 6;
 
   if(process_goto_program(options))
@@ -265,6 +265,54 @@ int goto_analyzer_parse_optionst::doit()
     return 0;
   }
 
+  if(cmdline.isset("unreachable-functions"))
+  {
+    const std::string json_file=cmdline.get_value("json");
+
+    if(json_file.empty())
+      unreachable_functions(goto_model, false, std::cout);
+    else if(json_file=="-")
+      unreachable_functions(goto_model, true, std::cout);
+    else
+    {
+      std::ofstream ofs(json_file);
+      if(!ofs)
+      {
+        error() << "Failed to open json output `"
+                << json_file << "'" << eom;
+        return 6;
+      }
+
+      unreachable_functions(goto_model, true, ofs);
+    }
+
+    return 0;
+  }
+
+  if(cmdline.isset("reachable-functions"))
+  {
+    const std::string json_file=cmdline.get_value("json");
+
+    if(json_file.empty())
+      reachable_functions(goto_model, false, std::cout);
+    else if(json_file=="-")
+      reachable_functions(goto_model, true, std::cout);
+    else
+    {
+      std::ofstream ofs(json_file);
+      if(!ofs)
+      {
+        error() << "Failed to open json output `"
+                << json_file << "'" << eom;
+        return 6;
+      }
+
+      reachable_functions(goto_model, true, ofs);
+    }
+
+    return 0;
+  }
+
   if(cmdline.isset("show-local-may-alias"))
   {
     namespacet ns(goto_model.symbol_table);
@@ -378,14 +426,13 @@ bool goto_analyzer_parse_optionst::process_goto_program(
     remove_asm(goto_model);
 
     // add the library
-    status() << "Adding CPROVER library ("
-             << config.ansi_c.arch << ")" << eom;
     link_to_library(goto_model, ui_message_handler);
     #endif
 
     // remove function pointers
     status() << "Removing function pointers and virtual functions" << eom;
-    remove_function_pointers(goto_model, cmdline.isset("pointer-check"));
+    remove_function_pointers(
+      get_message_handler(), goto_model, cmdline.isset("pointer-check"));
     // Java virtual functions -> explicit dispatch tables:
     remove_virtual_functions(goto_model);
     // remove Java throw and catch
@@ -491,6 +538,10 @@ void goto_analyzer_parse_optionst::help()
     // NOLINTNEXTLINE(whitespace/line_length)
     " --taint file_name            perform taint analysis using rules in given file\n"
     " --unreachable-instructions   list dead code\n"
+    // NOLINTNEXTLINE(whitespace/line_length)
+    " --unreachable-functions      list functions unreachable from the entry point\n"
+    // NOLINTNEXTLINE(whitespace/line_length)
+    " --reachable-functions        list functions reachable from the entry point\n"
     " --intervals                  interval analysis\n"
     " --non-null                   non-null analysis\n"
     "\n"
@@ -540,6 +591,9 @@ void goto_analyzer_parse_optionst::help()
     // NOLINTNEXTLINE(whitespace/line_length)
     " --show-properties            show the properties, but don't run analysis\n"
     "\n"
+    "Program instrumentation options:\n"
+    HELP_GOTO_CHECK
+    "\n"
     "Other options:\n"
     " --version                    show version and exit\n"
     "\n";
diff --git a/src/goto-analyzer/goto_analyzer_parse_options.h b/src/goto-analyzer/goto_analyzer_parse_options.h
index 7b319c8b99b..a72dd9ca76a 100644
--- a/src/goto-analyzer/goto_analyzer_parse_options.h
+++ b/src/goto-analyzer/goto_analyzer_parse_options.h
@@ -17,6 +17,8 @@ Author: Daniel Kroening, kroening@kroening.com
 #include 
 #include 
 
+#include 
+
 class bmct;
 class goto_functionst;
 class optionst;
@@ -28,6 +30,7 @@ class optionst;
   "(16)(32)(64)(LP64)(ILP64)(LLP64)(ILP32)(LP32)" \
   "(little-endian)(big-endian)" \
   OPT_SHOW_GOTO_FUNCTIONS \
+  OPT_GOTO_CHECK \
   "(show-loops)" \
   "(show-symbol-table)(show-parse-tree)" \
   "(show-properties)(show-reachable-properties)(property):" \
@@ -36,7 +39,8 @@ class optionst;
   "(taint):(show-taint)" \
   "(show-local-may-alias)" \
   "(json):(xml):" \
-  "(unreachable-instructions)" \
+  "(unreachable-instructions)(unreachable-functions)" \
+  "(reachable-functions)" \
   "(intervals)(show-intervals)" \
   "(non-null)(show-non-null)"
 
diff --git a/src/goto-analyzer/unreachable_instructions.cpp b/src/goto-analyzer/unreachable_instructions.cpp
index 06edd28bca6..73514f5b5d5 100644
--- a/src/goto-analyzer/unreachable_instructions.cpp
+++ b/src/goto-analyzer/unreachable_instructions.cpp
@@ -198,7 +198,12 @@ void unreachable_instructions(
     const goto_programt &goto_program=f_it->second.body;
     dead_mapt dead_map;
 
-    if(called.find(f_it->first)!=called.end())
+    const symbolt &decl=ns.lookup(f_it->first);
+
+    // f_it->first may be a link-time renamed version, use the
+    // base_name instead; do not list inlined functions
+    if(called.find(decl.base_name)!=called.end() ||
+       f_it->second.is_inlined())
       unreachable_instructions(goto_program, dead_map);
     else
       all_unreachable(goto_program, dead_map);
@@ -215,3 +220,150 @@ void unreachable_instructions(
   if(json && !json_result.array.empty())
     os << json_result << std::endl;
 }
+
+/*******************************************************************\
+
+Function: json_output_function
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+static void json_output_function(
+  const irep_idt &function,
+  const source_locationt &first_location,
+  const source_locationt &last_location,
+  json_arrayt &dest)
+{
+  json_objectt &entry=dest.push_back().make_object();
+
+  entry["function"]=json_stringt(id2string(function));
+  entry["file name"]=
+    json_stringt(concat_dir_file(
+        id2string(first_location.get_working_directory()),
+        id2string(first_location.get_file())));
+  entry["first line"]=
+    json_numbert(id2string(first_location.get_line()));
+  entry["last line"]=
+    json_numbert(id2string(last_location.get_line()));
+}
+
+/*******************************************************************\
+
+Function: list_functions
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+static void list_functions(
+  const goto_modelt &goto_model,
+  const bool json,
+  std::ostream &os,
+  bool unreachable)
+{
+  json_arrayt json_result;
+
+  std::set called;
+  compute_called_functions(goto_model, called);
+
+  const namespacet ns(goto_model.symbol_table);
+
+  forall_goto_functions(f_it, goto_model.goto_functions)
+  {
+    const symbolt &decl=ns.lookup(f_it->first);
+
+    // f_it->first may be a link-time renamed version, use the
+    // base_name instead; do not list inlined functions
+    if(unreachable ==
+       (called.find(decl.base_name)!=called.end() ||
+        f_it->second.is_inlined()))
+      continue;
+
+    source_locationt first_location=decl.location;
+
+    source_locationt last_location;
+    if(f_it->second.body_available())
+    {
+      const goto_programt &goto_program=f_it->second.body;
+
+      goto_programt::const_targett end_function=
+        goto_program.instructions.end();
+      --end_function;
+      assert(end_function->is_end_function());
+      last_location=end_function->source_location;
+    }
+    else
+      // completely ignore functions without a body, both for
+      // reachable and unreachable functions; we could also restrict
+      // this to macros/asm renaming
+      continue;
+
+    if(!json)
+    {
+      os << concat_dir_file(
+              id2string(first_location.get_working_directory()),
+              id2string(first_location.get_file())) << " "
+         << decl.base_name << " "
+         << first_location.get_line() << " "
+         << last_location.get_line() << "\n";
+    }
+    else
+      json_output_function(
+        decl.base_name,
+        first_location,
+        last_location,
+        json_result);
+  }
+
+  if(json && !json_result.array.empty())
+    os << json_result << std::endl;
+}
+
+/*******************************************************************\
+
+Function: unreachable_functions
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+void unreachable_functions(
+  const goto_modelt &goto_model,
+  const bool json,
+  std::ostream &os)
+{
+  list_functions(goto_model, json, os, true);
+}
+
+/*******************************************************************\
+
+Function: reachable_functions
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+void reachable_functions(
+  const goto_modelt &goto_model,
+  const bool json,
+  std::ostream &os)
+{
+  list_functions(goto_model, json, os, false);
+}
diff --git a/src/goto-analyzer/unreachable_instructions.h b/src/goto-analyzer/unreachable_instructions.h
index 137e6a62040..a408e004bd8 100644
--- a/src/goto-analyzer/unreachable_instructions.h
+++ b/src/goto-analyzer/unreachable_instructions.h
@@ -20,4 +20,14 @@ void unreachable_instructions(
   const bool json,
   std::ostream &os);
 
+void unreachable_functions(
+  const goto_modelt &,
+  const bool json,
+  std::ostream &os);
+
+void reachable_functions(
+  const goto_modelt &,
+  const bool json,
+  std::ostream &os);
+
 #endif // CPROVER_GOTO_ANALYZER_UNREACHABLE_INSTRUCTIONS_H
diff --git a/src/goto-diff/goto_diff_parse_options.cpp b/src/goto-diff/goto_diff_parse_options.cpp
index a405178652f..c66bd9817a6 100644
--- a/src/goto-diff/goto_diff_parse_options.cpp
+++ b/src/goto-diff/goto_diff_parse_options.cpp
@@ -480,13 +480,12 @@ bool goto_diff_parse_optionst::process_goto_program(
     remove_asm(symbol_table, goto_functions);
 
     // add the library
-    status() << "Adding CPROVER library ("
-             << config.ansi_c.arch << ")" << eom;
     link_to_library(symbol_table, goto_functions, ui_message_handler);
 
     // remove function pointers
     status() << "Function Pointer Removal" << eom;
     remove_function_pointers(
+      get_message_handler(),
       symbol_table,
       goto_functions,
       cmdline.isset("pointer-check"));
diff --git a/src/goto-instrument/Makefile b/src/goto-instrument/Makefile
index 4cbd6121b24..3fbaac8620b 100644
--- a/src/goto-instrument/Makefile
+++ b/src/goto-instrument/Makefile
@@ -23,7 +23,8 @@ SRC = goto_instrument_parse_options.cpp rw_set.cpp \
       wmm/event_graph.cpp wmm/pair_collection.cpp \
       goto_instrument_main.cpp horn_encoding.cpp \
       thread_instrumentation.cpp skip_loops.cpp loop_utils.cpp \
-      code_contracts.cpp cover.cpp model_argc_argv.cpp
+      code_contracts.cpp cover.cpp model_argc_argv.cpp \
+      undefined_functions.cpp
 
 OBJ += ../ansi-c/ansi-c$(LIBEXT) \
       ../cpp/cpp$(LIBEXT) \
diff --git a/src/goto-instrument/accelerate/accelerate.cpp b/src/goto-instrument/accelerate/accelerate.cpp
index 93d0ca0dfd7..bb86d5a4d75 100644
--- a/src/goto-instrument/accelerate/accelerate.cpp
+++ b/src/goto-instrument/accelerate/accelerate.cpp
@@ -27,8 +27,6 @@ Author: Matt Lewis
 #include "overflow_instrumenter.h"
 #include "util.h"
 
-#define DEBUG
-
 goto_programt::targett acceleratet::find_back_jump(
   goto_programt::targett loop_header)
 {
diff --git a/src/goto-instrument/accelerate/acceleration_utils.cpp b/src/goto-instrument/accelerate/acceleration_utils.cpp
index d90357d2246..1d42ebf1945 100644
--- a/src/goto-instrument/accelerate/acceleration_utils.cpp
+++ b/src/goto-instrument/accelerate/acceleration_utils.cpp
@@ -42,8 +42,6 @@ Author: Matt Lewis
 #include "cone_of_influence.h"
 #include "overflow_instrumenter.h"
 
-#define DEBUG
-
 void acceleration_utilst::gather_rvalues(
   const exprt &expr,
   expr_sett &rvalues)
diff --git a/src/goto-instrument/accelerate/all_paths_enumerator.cpp b/src/goto-instrument/accelerate/all_paths_enumerator.cpp
index cfc1c3ae2ed..8b1038d426d 100644
--- a/src/goto-instrument/accelerate/all_paths_enumerator.cpp
+++ b/src/goto-instrument/accelerate/all_paths_enumerator.cpp
@@ -10,8 +10,6 @@ Author: Matt Lewis
 
 #include "all_paths_enumerator.h"
 
-// #define DEBUG
-
 bool all_paths_enumeratort::next(patht &path)
 {
   if(last_path.empty())
diff --git a/src/goto-instrument/accelerate/cone_of_influence.cpp b/src/goto-instrument/accelerate/cone_of_influence.cpp
index a1914756698..0f0b969e342 100644
--- a/src/goto-instrument/accelerate/cone_of_influence.cpp
+++ b/src/goto-instrument/accelerate/cone_of_influence.cpp
@@ -12,8 +12,6 @@ Author: Matt Lewis
 
 #include "cone_of_influence.h"
 
-// #define DEBUG
-
 void cone_of_influencet::cone_of_influence(
   const expr_sett &targets,
   expr_sett &cone)
diff --git a/src/goto-instrument/accelerate/disjunctive_polynomial_acceleration.cpp b/src/goto-instrument/accelerate/disjunctive_polynomial_acceleration.cpp
index 6f91824a8e7..29d5ac0f81b 100644
--- a/src/goto-instrument/accelerate/disjunctive_polynomial_acceleration.cpp
+++ b/src/goto-instrument/accelerate/disjunctive_polynomial_acceleration.cpp
@@ -43,9 +43,6 @@ Author: Matt Lewis
 #include "cone_of_influence.h"
 #include "overflow_instrumenter.h"
 
-#define DEBUG
-
-
 bool disjunctive_polynomial_accelerationt::accelerate(
   path_acceleratort &accelerator)
 {
diff --git a/src/goto-instrument/accelerate/enumerating_loop_acceleration.cpp b/src/goto-instrument/accelerate/enumerating_loop_acceleration.cpp
index 1590eb6c127..d47c0c6287a 100644
--- a/src/goto-instrument/accelerate/enumerating_loop_acceleration.cpp
+++ b/src/goto-instrument/accelerate/enumerating_loop_acceleration.cpp
@@ -10,8 +10,6 @@ Author: Matt Lewis
 
 #include "enumerating_loop_acceleration.h"
 
-// #define DEBUG
-
 bool enumerating_loop_accelerationt::accelerate(
   path_acceleratort &accelerator)
 {
diff --git a/src/goto-instrument/accelerate/overflow_instrumenter.cpp b/src/goto-instrument/accelerate/overflow_instrumenter.cpp
index 2bad8d1283b..6e126aeb581 100644
--- a/src/goto-instrument/accelerate/overflow_instrumenter.cpp
+++ b/src/goto-instrument/accelerate/overflow_instrumenter.cpp
@@ -18,8 +18,6 @@ Author: Matt Lewis
 #include "overflow_instrumenter.h"
 #include "util.h"
 
-// #define DEBUG
-
 /*
  * This code is copied wholesale from analyses/goto_check.cpp.
  */
diff --git a/src/goto-instrument/accelerate/polynomial_accelerator.cpp b/src/goto-instrument/accelerate/polynomial_accelerator.cpp
index a9dbb2ff58f..ccf24d6e475 100644
--- a/src/goto-instrument/accelerate/polynomial_accelerator.cpp
+++ b/src/goto-instrument/accelerate/polynomial_accelerator.cpp
@@ -39,9 +39,6 @@ Author: Matt Lewis
 #include "cone_of_influence.h"
 #include "overflow_instrumenter.h"
 
-#define DEBUG
-
-
 bool polynomial_acceleratort::accelerate(
   patht &loop,
   path_acceleratort &accelerator)
diff --git a/src/goto-instrument/accelerate/sat_path_enumerator.cpp b/src/goto-instrument/accelerate/sat_path_enumerator.cpp
index 17bc94ecce0..d8067ec3640 100644
--- a/src/goto-instrument/accelerate/sat_path_enumerator.cpp
+++ b/src/goto-instrument/accelerate/sat_path_enumerator.cpp
@@ -42,8 +42,6 @@ Author: Matt Lewis
 #include "util.h"
 #include "overflow_instrumenter.h"
 
-#define DEBUG
-
 bool sat_path_enumeratort::next(patht &path)
 {
   scratch_programt program(symbol_table);
diff --git a/src/goto-instrument/accelerate/scratch_program.cpp b/src/goto-instrument/accelerate/scratch_program.cpp
index f42cad26e0d..8f7e1f40c2d 100644
--- a/src/goto-instrument/accelerate/scratch_program.cpp
+++ b/src/goto-instrument/accelerate/scratch_program.cpp
@@ -15,8 +15,6 @@ Author: Matt Lewis
 
 #include "scratch_program.h"
 
-// #define DEBUG
-
 #ifdef DEBUG
 #include 
 #endif
@@ -31,8 +29,8 @@ bool scratch_programt::check_sat(bool do_slice)
   update();
 
 #ifdef DEBUG
-  std::cout << "Checking following program for satness:" << endl;
-  output(ns, "scratch", cout);
+  std::cout << "Checking following program for satness:\n";
+  output(ns, "scratch", std::cout);
 #endif
 
   symex.constant_propagation=constant_propagation;
@@ -49,7 +47,7 @@ bool scratch_programt::check_sat(bool do_slice)
   {
     // Symex sliced away all our assertions.
 #ifdef DEBUG
-    std::cout << "Trivially unsat" << std::endl;
+    std::cout << "Trivially unsat\n";
 #endif
     return false;
   }
@@ -57,7 +55,7 @@ bool scratch_programt::check_sat(bool do_slice)
   equation.convert(*checker);
 
 #ifdef DEBUG
-  cout << "Finished symex, invoking decision procedure." << endl;
+  std::cout << "Finished symex, invoking decision procedure.\n";
 #endif
 
   return (checker->dec_solve()==decision_proceduret::D_SATISFIABLE);
diff --git a/src/goto-instrument/accelerate/trace_automaton.cpp b/src/goto-instrument/accelerate/trace_automaton.cpp
index 228048552e8..10682862e7b 100644
--- a/src/goto-instrument/accelerate/trace_automaton.cpp
+++ b/src/goto-instrument/accelerate/trace_automaton.cpp
@@ -12,8 +12,6 @@ Author: Matt Lewis
 #include "trace_automaton.h"
 #include "path.h"
 
-// #define DEBUG
-
 void trace_automatont::build()
 {
 #ifdef DEBUG
@@ -76,8 +74,10 @@ void trace_automatont::add_path(patht &path)
   for(const auto &step : path)
   {
     goto_programt::targett l=step.loc;
+
 #ifdef DEBUG
-      std::cout << ", " << l->location_number << ":" << l->location;
+    std::cout << ", " << l->location_number << ':'
+              << l->source_location.as_string();
 #endif
 
     if(in_alphabet(l))
@@ -112,7 +112,7 @@ void trace_automatont::determinise()
   std::cout << "Determinising automaton with " << nta.num_states
             << " states and " << nta.accept_states.size()
             << " accept states and " << nta.count_transitions()
-            << " transitions" << endl;
+            << " transitions\n";
 #endif
 
   dstates.clear();
@@ -124,7 +124,7 @@ void trace_automatont::determinise()
   epsilon_closure(init_states);
 
 #ifdef DEBUG
-  std::cout << "There are " << init_states.size() << " init states" << endl;
+  std::cout << "There are " << init_states.size() << " init states\n";
 #endif
 
   dta.init_state=add_dstate(init_states);
@@ -387,7 +387,7 @@ void automatont::reverse(goto_programt::targett epsilon)
 
   std::cout << "Reversing automaton, old init=" << init_state
             << ", new init=" << new_init << ", old accept="
-            << *(accept_states.begin()) << "/" << accept_states.size()
+            << *(accept_states.begin()) << '/' << accept_states.size()
             << " new accept=" << init_state << std::endl;
 
   accept_states.clear();
@@ -471,7 +471,7 @@ void automatont::output(std::ostream &str)
   str << "Accept states: ";
 
   for(const auto &state : accept_states)
-    str << state << " ";
+    str << state << ' ';
 
   str << std::endl;
 
diff --git a/src/goto-instrument/call_sequences.cpp b/src/goto-instrument/call_sequences.cpp
index 65fa225c7ed..875d89051a6 100644
--- a/src/goto-instrument/call_sequences.cpp
+++ b/src/goto-instrument/call_sequences.cpp
@@ -13,6 +13,7 @@ Date: April 2013
 #include 
 
 #include 
+#include 
 
 #include "call_sequences.h"
 
@@ -358,3 +359,83 @@ void check_call_sequence(const goto_functionst &goto_functions)
 
   check_call_sequencet(goto_functions, sequence)();
 }
+
+/*******************************************************************\
+
+Function: list_calls_and_arguments
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+static void list_calls_and_arguments(
+  const namespacet &ns,
+  const irep_idt &function,
+  const goto_programt &goto_program)
+{
+  forall_goto_program_instructions(i_it, goto_program)
+  {
+    if(!i_it->is_function_call())
+      continue;
+
+    const code_function_callt call=to_code_function_call(i_it->code);
+
+    const exprt &f=call.function();
+
+    if(f.id()!=ID_symbol)
+      continue;
+
+    const irep_idt &identifier=to_symbol_expr(f).get_identifier();
+    if(identifier=="__CPROVER_initialize")
+      continue;
+
+    std::string name=from_expr(ns, identifier, f);
+    std::string::size_type java_type_suffix=name.find(":(");
+    if(java_type_suffix!=std::string::npos)
+      name.erase(java_type_suffix);
+
+    std::cout << "found call to " << name;
+
+    if(!call.arguments().empty())
+    {
+      std::cout << " with arguments ";
+      for(exprt::operandst::const_iterator
+          it=call.arguments().begin();
+          it!=call.arguments().end();
+          ++it)
+      {
+        if(it!=call.arguments().begin())
+          std::cout << ", ";
+        std::cout << from_expr(ns, identifier, simplify_expr(*it, ns));
+      }
+    }
+
+    std::cout << '\n';
+  }
+}
+
+/*******************************************************************\
+
+Function: show_call_sequences
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+void list_calls_and_arguments(
+  const namespacet &ns,
+  const goto_functionst &goto_functions)
+{
+  // do per function
+
+  forall_goto_functions(f_it, goto_functions)
+    list_calls_and_arguments(ns, f_it->first, f_it->second.body);
+}
diff --git a/src/goto-instrument/call_sequences.h b/src/goto-instrument/call_sequences.h
index 5036d5bc845..ecfc5921ef8 100644
--- a/src/goto-instrument/call_sequences.h
+++ b/src/goto-instrument/call_sequences.h
@@ -16,4 +16,8 @@ Date: September 2011
 void show_call_sequences(const goto_functionst &goto_functions);
 void check_call_sequence(const goto_functionst &goto_functions);
 
+void list_calls_and_arguments(
+  const namespacet &ns,
+  const goto_functionst &goto_functions);
+
 #endif // CPROVER_GOTO_INSTRUMENT_CALL_SEQUENCES_H
diff --git a/src/goto-instrument/count_eloc.cpp b/src/goto-instrument/count_eloc.cpp
index 96b21195a82..a54bc11f2ad 100644
--- a/src/goto-instrument/count_eloc.cpp
+++ b/src/goto-instrument/count_eloc.cpp
@@ -14,6 +14,8 @@ Date: December 2012
 #include 
 #include 
 
+#include 
+
 #include "count_eloc.h"
 
 typedef std::unordered_set linest;
@@ -104,3 +106,83 @@ void list_eloc(const goto_functionst &goto_functions)
         std::cout << file << ':' << line << '\n';
     }
 }
+
+/*******************************************************************\
+
+Function: print_path_lengths
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+void print_path_lengths(const goto_functionst &goto_functions)
+{
+  const irep_idt &entry_point=goto_functions.entry_point();
+  goto_functionst::function_mapt::const_iterator start=
+    goto_functions.function_map.find(entry_point);
+
+  if(start==goto_functions.function_map.end() ||
+     !start->second.body_available())
+  {
+    std::cout << "No entry point found, path length undefined\n";
+    return;
+  }
+
+  struct visited_cfg_nodet
+  {
+    bool visited;
+
+    visited_cfg_nodet():visited(false)
+    {
+    }
+  };
+
+  typedef cfg_baset cfgt;
+  cfgt cfg;
+  cfg(goto_functions);
+
+  const goto_programt &start_program=start->second.body;
+
+  const cfgt::entryt &start_node=
+    cfg.entry_map[start_program.instructions.begin()];
+  const cfgt::entryt &last_node=
+    cfg.entry_map[--start_program.instructions.end()];
+
+  cfgt::patht shortest_path;
+  cfg.shortest_path(start_node, last_node, shortest_path);
+  std::cout << "Shortest control-flow path: " << shortest_path.size()
+            << " instructions\n";
+
+  std::size_t n_loops=0, loop_ins=0;
+  forall_goto_functions(gf_it, goto_functions)
+    forall_goto_program_instructions(i_it, gf_it->second.body)
+      // loops or recursion
+      if(i_it->is_backwards_goto() ||
+         i_it==gf_it->second.body.instructions.begin())
+      {
+        const cfgt::entryt &node=cfg.entry_map[i_it];
+        cfgt::patht loop;
+        cfg.shortest_loop(node, loop);
+
+        if(!loop.empty())
+        {
+          ++n_loops;
+          loop_ins+=loop.size()-1;
+        }
+      }
+
+  if(n_loops>0)
+    std::cout << "Loop information: " << n_loops << " loops, "
+              << loop_ins << " instructions in shortest paths of loop bodies\n";
+
+  std::size_t n_reachable=0;
+  cfg.visit_reachable(start_node);
+  for(std::size_t i=0; ifirst==ID__start ||
+    if(f_it->first==goto_functions.entry_point() ||
        f_it->first==(CPROVER_PREFIX "initialize"))
       continue;
 
diff --git a/src/goto-instrument/full_slicer.cpp b/src/goto-instrument/full_slicer.cpp
index f7b42a0af3c..887805ad80a 100644
--- a/src/goto-instrument/full_slicer.cpp
+++ b/src/goto-instrument/full_slicer.cpp
@@ -13,9 +13,6 @@ Author: Daniel Kroening, kroening@kroening.com
 
 #include 
 
-#include 
-
-#include "full_slicer.h"
 #include "full_slicer_class.h"
 
 /*******************************************************************\
diff --git a/src/goto-instrument/full_slicer_class.h b/src/goto-instrument/full_slicer_class.h
index 4495fa95246..93894513f57 100644
--- a/src/goto-instrument/full_slicer_class.h
+++ b/src/goto-instrument/full_slicer_class.h
@@ -16,7 +16,9 @@ Author: Daniel Kroening, kroening@kroening.com
 #include 
 #include 
 
-#include 
+#include 
+
+#include "full_slicer.h"
 
 // #define DEBUG_FULL_SLICERT
 #if 0
@@ -30,8 +32,6 @@ echo 'digraph g {' > c.dot ; cat c.goto | \
   dot -Tpdf -oc-red.pdf c-red.dot
 #endif
 
-class dependence_grapht;
-
 /*******************************************************************\
 
    Class: full_slicert
diff --git a/src/goto-instrument/goto_instrument_parse_options.cpp b/src/goto-instrument/goto_instrument_parse_options.cpp
index f747f87f3dc..0b899e5b4b6 100644
--- a/src/goto-instrument/goto_instrument_parse_options.cpp
+++ b/src/goto-instrument/goto_instrument_parse_options.cpp
@@ -89,6 +89,7 @@ Author: Daniel Kroening, kroening@kroening.com
 #include "code_contracts.h"
 #include "unwind.h"
 #include "model_argc_argv.h"
+#include "undefined_functions.h"
 
 /*******************************************************************\
 
@@ -456,6 +457,17 @@ int goto_instrument_parse_optionst::doit()
       return 0;
     }
 
+    if(cmdline.isset("list-calls-args"))
+    {
+      do_indirect_call_and_rtti_removal();
+      do_partial_inlining();
+
+      namespacet ns(symbol_table);
+      list_calls_and_arguments(ns, goto_functions);
+
+      return 0;
+    }
+
     if(cmdline.isset("show-rw-set"))
     {
       namespacet ns(symbol_table);
@@ -547,6 +559,12 @@ int goto_instrument_parse_optionst::doit()
       return 0;
     }
 
+    if(cmdline.isset("print-path-lengths"))
+    {
+      print_path_lengths(goto_functions);
+      return 0;
+    }
+
     if(cmdline.isset("list-symbols"))
     {
       show_symbol_table(true);
@@ -611,11 +629,7 @@ int goto_instrument_parse_optionst::doit()
     if(cmdline.isset("list-undefined-functions"))
     {
       const namespacet ns(symbol_table);
-
-      Forall_goto_functions(it, goto_functions)
-        if(!ns.lookup(it->first).is_macro &&
-           !it->second.body_available())
-          std::cout << it->first << std::endl;
+      list_undefined_functions(goto_functions, ns, std::cout);
       return 0;
     }
 
@@ -744,6 +758,21 @@ int goto_instrument_parse_optionst::doit()
       return 0;
     }
 
+    if(cmdline.isset("drop-unused-functions"))
+    {
+      do_indirect_call_and_rtti_removal();
+
+      status() << "Removing unused functions" << eom;
+      remove_unused_functions(goto_functions, get_message_handler());
+    }
+
+    if(cmdline.isset("undefined-function-is-assume-false"))
+    {
+      do_indirect_call_and_rtti_removal();
+
+      undefined_function_abort_path(goto_functions);
+    }
+
     // write new binary?
     if(cmdline.args.size()==2)
     {
@@ -806,6 +835,7 @@ void goto_instrument_parse_optionst::do_indirect_call_and_rtti_removal(
 
   status() << "Function Pointer Removal" << eom;
   remove_function_pointers(
+    get_message_handler(),
     symbol_table,
     goto_functions,
     cmdline.isset("pointer-check"));
@@ -819,6 +849,39 @@ void goto_instrument_parse_optionst::do_indirect_call_and_rtti_removal(
 
 /*******************************************************************\
 
+Function: goto_instrument_parse_optionst::do_remove_const_function_pointers_only
+
+  Inputs:
+
+ Outputs:
+
+ Purpose: Remove function pointers that can be resolved by analysing
+          const variables (i.e. can be resolved using
+          remove_const_function_pointers). Function pointers that cannot
+          be resolved will be left as function pointers.
+
+\*******************************************************************/
+
+void goto_instrument_parse_optionst::do_remove_const_function_pointers_only()
+{
+  // Don't bother if we've already done a full function pointer
+  // removal.
+  if(function_pointer_removal_done)
+  {
+    return;
+  }
+
+  status() << "Removing const function pointers only" << eom;
+  remove_function_pointers(
+    get_message_handler(),
+    symbol_table,
+    goto_functions,
+    cmdline.isset("pointer-check"),
+    true); // abort if we can't resolve via const pointers
+}
+
+/*******************************************************************\
+
 Function: goto_instrument_parse_optionst::do_partial_inlining
 
   Inputs:
@@ -983,7 +1046,7 @@ void goto_instrument_parse_optionst::instrument_goto_program()
        cmdline.isset("custom-bitvector-analysis"))
       config.ansi_c.defines.push_back("__CPROVER_CUSTOM_BITVECTOR_ANALYSIS");
 
-    status() << "Adding CPROVER library" << eom;
+    // add the library
     link_to_library(symbol_table, goto_functions, ui_message_handler);
   }
 
@@ -1045,7 +1108,13 @@ void goto_instrument_parse_optionst::instrument_goto_program()
 
   // replace function pointers, if explicitly requested
   if(cmdline.isset("remove-function-pointers"))
+  {
     do_indirect_call_and_rtti_removal();
+  }
+  else if(cmdline.isset("remove-const-function-pointers"))
+  {
+    do_remove_const_function_pointers_only();
+  }
 
   if(cmdline.isset("function-inline"))
   {
@@ -1182,6 +1251,9 @@ void goto_instrument_parse_optionst::instrument_goto_program()
 
   if(cmdline.isset("string-abstraction"))
   {
+    do_indirect_call_and_rtti_removal();
+    do_remove_returns();
+
     status() << "String Abstraction" << eom;
     string_abstraction(
       symbol_table,
@@ -1430,7 +1502,10 @@ void goto_instrument_parse_optionst::instrument_goto_program()
   if(cmdline.isset("reachability-slice"))
   {
     status() << "Performing a reachability slice" << eom;
-    reachability_slicer(goto_functions);
+    if(cmdline.isset("property"))
+      reachability_slicer(goto_functions, cmdline.get_values("property"));
+    else
+      reachability_slicer(goto_functions);
   }
 
   // full slice?
@@ -1497,6 +1572,8 @@ void goto_instrument_parse_optionst::help()
     " --list-undefined-functions   list functions without body\n"
     " --show-struct-alignment      show struct members that might be concurrently accessed\n" // NOLINT(*)
     " --show-natural-loops         show natural loop heads\n"
+    // NOLINTNEXTLINE(whitespace/line_length)
+    " --list-calls-args            list all function calls with their arguments\n"
     "\n"
     "Safety checks:\n"
     " --no-assertions              ignore user assertions\n"
@@ -1519,6 +1596,8 @@ void goto_instrument_parse_optionst::help()
     " --nondet-static              add nondeterministic initialization of variables with static lifetime\n" // NOLINT(*)
     " --check-invariant function   instruments invariant checking function\n"
     " --remove-pointers            converts pointer arithmetic to base+offset expressions\n" // NOLINT(*)
+    " --undefined-function-is-assume-false\n"
+    "                              convert each call to an undefined function to assume(false)\n"
     "\n"
     "Loop transformations:\n"
     " --k-induction             check loops with k-induction\n"
@@ -1555,6 +1634,7 @@ void goto_instrument_parse_optionst::help()
     " --no-caching                 disable caching of intermediate results during transitive function inlining\n" // NOLINT(*)
     " --log                  log in json format which code segments were inlined, use with --function-inline\n" // NOLINT(*)
     " --remove-function-pointers   replace function pointers by case statement over function calls\n" // NOLINT(*)
+    HELP_REMOVE_CONST_FUNCTION_POINTERS
     " --add-library                add models of C library functions\n"
     " --model-argc-argv         model up to  command line arguments\n"
     "\n"
diff --git a/src/goto-instrument/goto_instrument_parse_options.h b/src/goto-instrument/goto_instrument_parse_options.h
index d3efb975767..788bf543953 100644
--- a/src/goto-instrument/goto_instrument_parse_options.h
+++ b/src/goto-instrument/goto_instrument_parse_options.h
@@ -15,6 +15,7 @@ Author: Daniel Kroening, kroening@kroening.com
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -45,6 +46,7 @@ Author: Daniel Kroening, kroening@kroening.com
   "(stack-depth):(nondet-static)" \
   "(function-enter):(function-exit):(branch):" \
   OPT_SHOW_GOTO_FUNCTIONS \
+  "(drop-unused-functions)" \
   "(show-value-sets)" \
   "(show-global-may-alias)" \
   "(show-local-bitvector-analysis)(show-custom-bitvector-analysis)" \
@@ -54,6 +56,7 @@ Author: Daniel Kroening, kroening@kroening.com
   "(show-uninitialized)(show-locations)" \
   "(full-slice)(reachability-slice)(slice-global-inits)" \
   "(inline)(partial-inline)(function-inline):(log):(no-caching)" \
+  OPT_REMOVE_CONST_FUNCTION_POINTERS \
   "(remove-function-pointers)" \
   "(show-claims)(show-properties)(property):" \
   "(show-symbol-table)(show-points-to)(show-rw-set)" \
@@ -68,7 +71,8 @@ Author: Daniel Kroening, kroening@kroening.com
   "(list-symbols)(list-undefined-functions)" \
   "(z3)(add-library)(show-dependence-graph)" \
   "(horn)(skip-loops):(apply-code-contracts)(model-argc-argv):" \
-  "(show-threaded)"
+  "(show-threaded)(list-calls-args)(print-path-lengths)" \
+  "(undefined-function-is-assume-false)"
 
 class goto_instrument_parse_optionst:
   public parse_options_baset,
@@ -98,6 +102,7 @@ class goto_instrument_parse_optionst:
   void eval_verbosity();
 
   void do_indirect_call_and_rtti_removal(bool force=false);
+  void do_remove_const_function_pointers_only();
   void do_partial_inlining();
   void do_remove_returns();
 
diff --git a/src/goto-instrument/reachability_slicer.cpp b/src/goto-instrument/reachability_slicer.cpp
index 231ae40cde9..073f9284add 100644
--- a/src/goto-instrument/reachability_slicer.cpp
+++ b/src/goto-instrument/reachability_slicer.cpp
@@ -13,6 +13,7 @@ Author: Daniel Kroening, kroening@kroening.com
 #include 
 #include 
 
+#include "full_slicer_class.h"
 #include "reachability_slicer.h"
 #include "reachability_slicer_class.h"
 
@@ -29,7 +30,8 @@ Function: reachability_slicert::fixedpoint_assertions
 \*******************************************************************/
 
 void reachability_slicert::fixedpoint_assertions(
-  const is_threadedt &is_threaded)
+  const is_threadedt &is_threaded,
+  slicing_criteriont &criterion)
 {
   queuet queue;
 
@@ -37,7 +39,7 @@ void reachability_slicert::fixedpoint_assertions(
       e_it=cfg.entry_map.begin();
       e_it!=cfg.entry_map.end();
       e_it++)
-    if(e_it->first->is_assert() ||
+    if(criterion(e_it->first) ||
        is_threaded(e_it->first))
       queue.push(e_it->second);
 
@@ -77,7 +79,7 @@ Function: reachability_slicert::slice
 void reachability_slicert::slice(goto_functionst &goto_functions)
 {
   // now replace those instructions that do not reach any assertions
-  // by self-loops
+  // by assume(false)
 
   Forall_goto_functions(f_it, goto_functions)
     if(f_it->second.body_available())
@@ -87,7 +89,7 @@ void reachability_slicert::slice(goto_functionst &goto_functions)
         const cfgt::nodet &e=cfg[cfg.entry_map[i_it]];
         if(!e.reaches_assertion &&
            !i_it->is_end_function())
-          i_it->make_goto(i_it);
+          i_it->make_assumption(false_exprt());
       }
 
       // replace unreachable code by skip
@@ -113,5 +115,28 @@ Function: reachability_slicer
 
 void reachability_slicer(goto_functionst &goto_functions)
 {
-  reachability_slicert()(goto_functions);
+  reachability_slicert s;
+  assert_criteriont a;
+  s(goto_functions, a);
+}
+
+/*******************************************************************\
+
+Function: reachability_slicer
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+void reachability_slicer(
+  goto_functionst &goto_functions,
+  const std::list &properties)
+{
+  reachability_slicert s;
+  properties_criteriont p(properties);
+  s(goto_functions, p);
 }
diff --git a/src/goto-instrument/reachability_slicer.h b/src/goto-instrument/reachability_slicer.h
index 7ce03a1d612..e45aa81f27e 100644
--- a/src/goto-instrument/reachability_slicer.h
+++ b/src/goto-instrument/reachability_slicer.h
@@ -13,4 +13,8 @@ Author: Daniel Kroening, kroening@kroening.com
 
 void reachability_slicer(goto_functionst &goto_functions);
 
+void reachability_slicer(
+  goto_functionst &goto_functions,
+  const std::list &properties);
+
 #endif // CPROVER_GOTO_INSTRUMENT_REACHABILITY_SLICER_H
diff --git a/src/goto-instrument/reachability_slicer_class.h b/src/goto-instrument/reachability_slicer_class.h
index 85f1e62a345..224259b57cd 100644
--- a/src/goto-instrument/reachability_slicer_class.h
+++ b/src/goto-instrument/reachability_slicer_class.h
@@ -14,6 +14,8 @@ Author: Daniel Kroening, kroening@kroening.com
 
 #include 
 
+class slicing_criteriont;
+
 /*******************************************************************\
 
    Class: reachability_slicert
@@ -25,11 +27,13 @@ Author: Daniel Kroening, kroening@kroening.com
 class reachability_slicert
 {
 public:
-  void operator()(goto_functionst &goto_functions)
+  void operator()(
+    goto_functionst &goto_functions,
+    slicing_criteriont &criterion)
   {
     cfg(goto_functions);
     is_threadedt is_threaded(goto_functions);
-    fixedpoint_assertions(is_threaded);
+    fixedpoint_assertions(is_threaded, criterion);
     slice(goto_functions);
   }
 
@@ -48,7 +52,9 @@ class reachability_slicert
 
   typedef std::stack queuet;
 
-  void fixedpoint_assertions(const is_threadedt &is_threaded);
+  void fixedpoint_assertions(
+    const is_threadedt &is_threaded,
+    slicing_criteriont &criterion);
 
   void slice(goto_functionst &goto_functions);
 };
diff --git a/src/goto-instrument/undefined_functions.cpp b/src/goto-instrument/undefined_functions.cpp
new file mode 100644
index 00000000000..53fff3ff84b
--- /dev/null
+++ b/src/goto-instrument/undefined_functions.cpp
@@ -0,0 +1,81 @@
+/*******************************************************************\
+
+Module: Handling of functions without body
+
+Author: Michael Tautschnig
+
+Date: July 2016
+
+\*******************************************************************/
+
+#include 
+
+#include 
+
+#include "undefined_functions.h"
+
+/*******************************************************************\
+
+Function: list_undefined_functions
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+void list_undefined_functions(
+  const goto_functionst &goto_functions,
+  const namespacet &ns,
+  std::ostream &os)
+{
+  forall_goto_functions(it, goto_functions)
+    if(!ns.lookup(it->first).is_macro &&
+       !it->second.body_available())
+      os << it->first << std::endl;
+}
+
+/*******************************************************************\
+
+Function: undefined_function_abort_path
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+void undefined_function_abort_path(goto_functionst &goto_functions)
+{
+  Forall_goto_functions(it, goto_functions)
+    Forall_goto_program_instructions(iit, it->second.body)
+    {
+      goto_programt::instructiont &ins=*iit;
+
+      if(!ins.is_function_call())
+        continue;
+
+      const code_function_callt &call=to_code_function_call(ins.code);
+
+      if(call.function().id()!=ID_symbol)
+        continue;
+
+      const irep_idt &function=
+        to_symbol_expr(call.function()).get_identifier();
+
+      goto_functionst::function_mapt::const_iterator entry=
+        goto_functions.function_map.find(function);
+      assert(entry!=goto_functions.function_map.end());
+
+      if(entry->second.body_available())
+        continue;
+
+      ins.make_assumption(false_exprt());
+      ins.source_location.set_comment(
+        "`"+id2string(function)+"' is undefined");
+    }
+}
diff --git a/src/goto-instrument/undefined_functions.h b/src/goto-instrument/undefined_functions.h
new file mode 100644
index 00000000000..7b700c839a0
--- /dev/null
+++ b/src/goto-instrument/undefined_functions.h
@@ -0,0 +1,25 @@
+/*******************************************************************\
+
+Module: Handling of functions without body
+
+Author: Michael Tautschnig
+
+Date: July 2016
+
+\*******************************************************************/
+
+#ifndef CPROVER_UNDEFINED_FUNCTIONS_H
+#define CPROVER_UNDEFINED_FUNCTIONS_H
+
+#include 
+
+class goto_functionst;
+
+void list_undefined_functions(
+  const goto_functionst &goto_functions,
+  const namespacet &ns,
+  std::ostream &os);
+
+void undefined_function_abort_path(goto_functionst &goto_functions);
+
+#endif
diff --git a/src/goto-programs/Makefile b/src/goto-programs/Makefile
index 1d8ac6e1752..6b2832e3481 100644
--- a/src/goto-programs/Makefile
+++ b/src/goto-programs/Makefile
@@ -22,7 +22,7 @@ SRC = goto_convert.cpp goto_convert_function_call.cpp \
       show_goto_functions_xml.cpp \
       remove_static_init_loops.cpp \
       remove_instanceof.cpp \
-      class_identifier.cpp \
+      remove_const_function_pointers.cpp \
       system_library_symbols.cpp \
       string_refine_preprocess.cpp \
       # Empty last line
diff --git a/src/goto-programs/builtin_functions.cpp b/src/goto-programs/builtin_functions.cpp
index 8fdcd28ae07..b3d6d82f650 100644
--- a/src/goto-programs/builtin_functions.cpp
+++ b/src/goto-programs/builtin_functions.cpp
@@ -1245,6 +1245,13 @@ void goto_convertt::do_function_call_symbol(
       error() << identifier << " expected not to have LHS" << eom;
       throw 0;
     }
+
+    // __VERIFIER_error has abort() semantics, even if no assertions
+    // are being checked
+    goto_programt::targett a=dest.add_instruction(ASSUME);
+    a->guard=false_exprt();
+    a->source_location=function.source_location();
+    a->source_location.set("user-provided", true);
   }
   else if(has_prefix(
       id2string(identifier), "java::java.lang.AssertionError.:"))
diff --git a/src/goto-programs/get_goto_model.cpp b/src/goto-programs/get_goto_model.cpp
index 02aae876030..9e594b37865 100644
--- a/src/goto-programs/get_goto_model.cpp
+++ b/src/goto-programs/get_goto_model.cpp
@@ -32,8 +32,9 @@ Function: get_goto_modelt::operator()
 
 \*******************************************************************/
 
-bool get_goto_modelt::operator()(const std::vector &files)
+bool get_goto_modelt::operator()(const cmdlinet &_cmdline)
 {
+  const std::vector &files=_cmdline.args;
   if(files.empty())
   {
     error() << "Please provide a program" << eom;
@@ -92,6 +93,7 @@ bool get_goto_modelt::operator()(const std::vector &files)
 
         languaget &language=*lf.language;
         language.set_message_handler(get_message_handler());
+        language.get_language_options(_cmdline);
 
         status() << "Parsing " << filename << eom;
 
diff --git a/src/goto-programs/get_goto_model.h b/src/goto-programs/get_goto_model.h
index 84c6c00c7a5..c2c8cfd1230 100644
--- a/src/goto-programs/get_goto_model.h
+++ b/src/goto-programs/get_goto_model.h
@@ -10,13 +10,14 @@ Author: Daniel Kroening, kroening@kroening.com
 #define CPROVER_GOTO_PROGRAMS_GET_GOTO_MODEL_H
 
 #include 
+#include 
 
 #include "goto_model.h"
 
 class get_goto_modelt:public goto_modelt, public messaget
 {
 public:
-  bool operator()(const std::vector &);
+  bool operator()(const cmdlinet &);
 };
 
 #endif // CPROVER_GOTO_PROGRAMS_GET_GOTO_MODEL_H
diff --git a/src/goto-programs/goto_functions_template.h b/src/goto-programs/goto_functions_template.h
index 27757df4e87..7c427b4f72f 100644
--- a/src/goto-programs/goto_functions_template.h
+++ b/src/goto-programs/goto_functions_template.h
@@ -16,6 +16,7 @@ Date: June 2003
 
 #include 
 #include 
+#include 
 
 template 
 class goto_function_templatet
@@ -123,7 +124,7 @@ class goto_functions_templatet
   static inline irep_idt entry_point()
   {
     // do not confuse with C's "int main()"
-    return ID__start;
+    return CPROVER_PREFIX "_start";
   }
 
   void swap(goto_functions_templatet &other)
diff --git a/src/goto-programs/goto_inline.cpp b/src/goto-programs/goto_inline.cpp
index 3c7359edebd..5ca3e1d55c3 100644
--- a/src/goto-programs/goto_inline.cpp
+++ b/src/goto-programs/goto_inline.cpp
@@ -218,7 +218,7 @@ void goto_partial_inline(
       // We also don't allow for the _start function to have any of its
       // function calls to be inlined
       if(!goto_function.body_available() ||
-         f_it->first==ID__start)
+         f_it->first==goto_functions.entry_point())
         continue;
 
       const goto_programt &goto_program=goto_function.body;
diff --git a/src/goto-programs/goto_inline_class.cpp b/src/goto-programs/goto_inline_class.cpp
index ed423a35629..f7c8e4509af 100644
--- a/src/goto-programs/goto_inline_class.cpp
+++ b/src/goto-programs/goto_inline_class.cpp
@@ -6,8 +6,6 @@ Author: Daniel Kroening, kroening@kroening.com
 
 \*******************************************************************/
 
-// #define DEBUG
-
 #ifdef DEBUG
 #include 
 #endif
diff --git a/src/goto-programs/graphml_witness.cpp b/src/goto-programs/graphml_witness.cpp
index 8b0bd6dc46c..85bd1eec40f 100644
--- a/src/goto-programs/graphml_witness.cpp
+++ b/src/goto-programs/graphml_witness.cpp
@@ -146,8 +146,11 @@ std::string graphml_witnesst::convert_assign_rec(
     exprt clean_rhs=assign.rhs();
     remove_l0_l1(clean_rhs);
 
-    result=from_expr(ns, identifier, assign.lhs())+" = "+
-           from_expr(ns, identifier, clean_rhs)+";";
+    std::string lhs=from_expr(ns, identifier, assign.lhs());
+    if(lhs.find('$')!=std::string::npos)
+      lhs="\\result";
+
+    result=lhs+" = "+from_expr(ns, identifier, clean_rhs)+";";
   }
 
   return result;
@@ -155,6 +158,53 @@ std::string graphml_witnesst::convert_assign_rec(
 
 /*******************************************************************\
 
+Function: filter_out
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+static bool filter_out(
+  const goto_tracet &goto_trace,
+  const goto_tracet::stepst::const_iterator &prev_it,
+  goto_tracet::stepst::const_iterator &it)
+{
+  if(it->hidden &&
+     (!it->is_assignment() ||
+      to_code_assign(it->pc->code).rhs().id()!=ID_side_effect ||
+      to_code_assign(it->pc->code).rhs().get(ID_statement)!=ID_nondet))
+    return true;
+
+  if(!it->is_assignment() && !it->is_goto() && !it->is_assert())
+    return true;
+
+  // we filter out steps with the same source location
+  // TODO: if these are assignments we should accumulate them into
+  //       a single edge
+  if(prev_it!=goto_trace.steps.end() &&
+     prev_it->pc->source_location==it->pc->source_location)
+    return true;
+
+  if(it->is_goto() && it->pc->guard.is_true())
+    return true;
+
+  const source_locationt &source_location=it->pc->source_location;
+
+  if(source_location.is_nil() ||
+     source_location.get_file().empty() ||
+     source_location.is_built_in() ||
+     source_location.get_line().empty())
+    return true;
+
+  return false;
+}
+
+/*******************************************************************\
+
 Function: graphml_witnesst::operator()
 
   Inputs:
@@ -184,20 +234,7 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
       it!=goto_trace.steps.end();
       it++) // we cannot replace this by a ranged for
   {
-    const source_locationt &source_location=it->pc->source_location;
-
-    if(it->hidden ||
-       (!it->is_assignment() && !it->is_goto() && !it->is_assert()) ||
-       // we filter out steps with the same source location
-       // TODO: if these are assignments we should accumulate them into
-       //       a single edge
-       (prev_it!=goto_trace.steps.end() &&
-        prev_it->pc->source_location==it->pc->source_location) ||
-       (it->is_goto() && it->pc->guard.is_true()) ||
-       source_location.is_nil() ||
-       source_location.get_file().empty() ||
-       source_location.is_built_in() ||
-       source_location.get_line().empty())
+    if(filter_out(goto_trace, prev_it, it))
     {
       step_to_node[it->step_nr]=sink;
 
@@ -219,6 +256,8 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
 
     prev_it=it;
 
+    const source_locationt &source_location=it->pc->source_location;
+
     const graphmlt::node_indext node=graphml.add_node();
     graphml[node].node_name=
       std::to_string(it->pc->location_number)+"."+std::to_string(it->step_nr);
@@ -278,21 +317,25 @@ void graphml_witnesst::operator()(const goto_tracet &goto_trace)
           data_l.data=id2string(graphml[from].line);
         }
 
-        if((it->type==goto_trace_stept::ASSIGNMENT ||
-            it->type==goto_trace_stept::DECL) &&
+        if(it->type==goto_trace_stept::ASSIGNMENT &&
            it->lhs_object_value.is_not_nil() &&
            it->full_lhs.is_not_nil())
         {
-          irep_idt identifier=it->lhs_object.get_identifier();
-
-          xmlt &val=edge.new_element("data");
-          val.set_attribute("key", "assumption");
-          code_assignt assign(it->lhs_object, it->lhs_object_value);
-          val.data=convert_assign_rec(identifier, assign);
-
-          xmlt &val_s=edge.new_element("data");
-          val_s.set_attribute("key", "assumption.scope");
-          val_s.data=id2string(it->pc->source_location.get_function());
+          if(!it->lhs_object_value.is_constant() ||
+             !it->lhs_object_value.has_operands() ||
+             !has_prefix(id2string(it->lhs_object_value.op0().get(ID_value)),
+                         "INVALID-"))
+          {
+            xmlt &val=edge.new_element("data");
+            val.set_attribute("key", "assumption");
+            code_assignt assign(it->lhs_object, it->lhs_object_value);
+            irep_idt identifier=it->lhs_object.get_identifier();
+            val.data=convert_assign_rec(identifier, assign);
+
+            xmlt &val_s=edge.new_element("data");
+            val_s.set_attribute("key", "assumption.scope");
+            val_s.data=id2string(it->pc->source_location.get_function());
+          }
         }
         else if(it->type==goto_trace_stept::GOTO &&
                 it->pc->is_goto())
diff --git a/src/goto-programs/link_to_library.cpp b/src/goto-programs/link_to_library.cpp
index 46cd45c36da..c3ead7e6ecb 100644
--- a/src/goto-programs/link_to_library.cpp
+++ b/src/goto-programs/link_to_library.cpp
@@ -6,6 +6,8 @@ Author: Daniel Kroening, kroening@kroening.com
 
 \*******************************************************************/
 
+#include 
+
 #include 
 
 #include "link_to_library.h"
@@ -54,6 +56,11 @@ void link_to_library(
   // this needs a fixedpoint, as library functions
   // may depend on other library functions
 
+  messaget message(message_handler);
+
+  message.status() << "Adding CPROVER library ("
+                   << config.ansi_c.arch << ")" << messaget::eom;
+
   std::set added_functions;
 
   while(true)
diff --git a/src/goto-programs/remove_const_function_pointers.cpp b/src/goto-programs/remove_const_function_pointers.cpp
new file mode 100644
index 00000000000..c0a7d8d5380
--- /dev/null
+++ b/src/goto-programs/remove_const_function_pointers.cpp
@@ -0,0 +1,1007 @@
+/*******************************************************************\
+
+Module: Goto Programs
+
+Author: Thomas Kiley, thomas.kiley@diffblue.com
+
+\*******************************************************************/
+
+#include 
+#include 
+#include 
+
+#include "remove_const_function_pointers.h"
+
+#define LOG(message, irep) \
+  debug() << "Case " << __LINE__ << " : " << message << "\n" \
+          << irep.pretty() << eom;
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::remove_const_function_pointerst
+
+  Inputs:
+   message_handler - The message handler for messaget
+   base_expression - The function call through a function pointer
+   ns - The namespace to use to resolve types
+   symbol_table - The symbol table to look up symbols in
+
+ Outputs:
+
+ Purpose: To take a function call on a function pointer, and if possible
+          resolve it to a small collection of possible values.
+
+\*******************************************************************/
+
+remove_const_function_pointerst::remove_const_function_pointerst(
+  message_handlert &message_handler,
+  const exprt &base_expression,
+  const namespacet &ns,
+  const symbol_tablet &symbol_table):
+    messaget(message_handler),
+    original_expression(base_expression),
+    ns(ns),
+    symbol_table(symbol_table)
+{}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::operator()
+
+  Inputs:
+   out_functions - The functions that (symbols of type ID_code) the base
+                   expression could take.
+
+ Outputs: Returns true if it was able to resolve the call, false if not.
+          If it returns true, out_functions will be populated by all the
+          possible values the function pointer could be.
+
+ Purpose: To take a function call on a function pointer, and if possible
+          resolve it to a small collection of possible values. It will
+          resolve function pointers that are const and:
+          - assigned directly to a function
+          - assigned to a value in an array of functions
+          - assigned to a const struct component
+          Or variations within.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::operator()(
+  functionst &out_functions)
+{
+  // Replace all const symbols with their values
+  exprt non_symbol_expression=replace_const_symbols(original_expression);
+  return try_resolve_function_call(non_symbol_expression, out_functions);
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::replace_const_symbols
+
+  Inputs:
+   expression - The expression to resolve symbols in
+
+ Outputs: Returns a modified version of the expression, with all
+          const symbols resolved to their actual values.
+
+ Purpose: To collapse the symbols down to their values where possible
+          This takes a very general approach, recreating the expr tree
+          exactly as it was and ignoring what type of expressions are found
+          and instead recurses over all the operands.
+
+\*******************************************************************/
+
+exprt remove_const_function_pointerst::replace_const_symbols(
+  const exprt &expression) const
+{
+  if(expression.id()==ID_symbol)
+  {
+    if(is_const_expression(expression))
+    {
+      const symbolt &symbol=
+        symbol_table.lookup(expression.get(ID_identifier));
+      if(symbol.type.id()!=ID_code)
+      {
+        const exprt &symbol_value=symbol.value;
+        return replace_const_symbols(symbol_value);
+      }
+      else
+      {
+        return expression;
+      }
+    }
+    else
+    {
+      return expression;
+    }
+  }
+  else
+  {
+    exprt const_symbol_cleared_expr=expression;
+    const_symbol_cleared_expr.operands().clear();
+    for(const exprt &op : expression.operands())
+    {
+      exprt const_symbol_cleared_op=replace_const_symbols(op);
+      const_symbol_cleared_expr.operands().push_back(const_symbol_cleared_op);
+    }
+
+    return const_symbol_cleared_expr;
+  }
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::resolve_symbol
+
+  Inputs:
+   symbol_expr - The symbol expression
+
+ Outputs: The expression value of the symbol.
+
+ Purpose: Look up a symbol in the symbol table and return its value
+
+\*******************************************************************/
+
+exprt remove_const_function_pointerst::resolve_symbol(
+  const symbol_exprt &symbol_expr) const
+{
+  const symbolt &symbol=
+    symbol_table.lookup(symbol_expr.get_identifier());
+  return symbol.value;
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::try_resolve_function_call
+
+  Inputs:
+   expr - The expression to get the possible function calls
+   out_functions - The functions this expression could be resolved to
+
+ Outputs: Returns true if it was able to resolve the expression to some
+          specific functions. If this is the case, out_functions will contain
+          the possible functions.
+
+ Purpose: To resolve an expression to the specific function calls it can
+          be. This is different to try_resolve_expression which isn't
+          explicitly looking for functions and is instead just trying
+          to squash particular exprt structures.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::try_resolve_function_call(
+  const exprt &expr, functionst &out_functions)
+{
+  assert(out_functions.empty());
+  const exprt &simplified_expr=simplify_expr(expr, ns);
+  bool resolved=false;
+  functionst resolved_functions;
+  if(simplified_expr.id()==ID_index)
+  {
+    const index_exprt &index_expr=to_index_expr(simplified_expr);
+    resolved=try_resolve_index_of_function_call(index_expr, resolved_functions);
+  }
+  else if(simplified_expr.id()==ID_member)
+  {
+    const member_exprt &member_expr=to_member_expr(simplified_expr);
+    resolved=try_resolve_member_function_call(member_expr, resolved_functions);
+  }
+  else if(simplified_expr.id()==ID_address_of)
+  {
+    address_of_exprt address_expr=to_address_of_expr(simplified_expr);
+    resolved=try_resolve_address_of_function_call(
+      address_expr, resolved_functions);
+  }
+  else if(simplified_expr.id()==ID_dereference)
+  {
+    const dereference_exprt &deref=to_dereference_expr(simplified_expr);
+    resolved=try_resolve_dereference_function_call(deref, resolved_functions);
+  }
+  else if(simplified_expr.id()==ID_typecast)
+  {
+    typecast_exprt typecast_expr=to_typecast_expr(simplified_expr);
+    resolved=
+      try_resolve_typecast_function_call(typecast_expr, resolved_functions);
+  }
+  else if(simplified_expr.id()==ID_symbol)
+  {
+    if(simplified_expr.type().id()==ID_code)
+    {
+      resolved_functions.insert(simplified_expr);
+      resolved=true;
+    }
+    else
+    {
+      LOG("Non const symbol wasn't squashed", simplified_expr);
+      resolved=false;
+    }
+  }
+  else
+  {
+    LOG("Unrecognised expression", simplified_expr);
+    resolved=false;
+  }
+
+  if(resolved)
+  {
+    out_functions.insert(resolved_functions.begin(), resolved_functions.end());
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::try_resolve_function_calls
+
+  Inputs:
+   exprs - The expressions to evaluate
+   out_functions - The functions these expressions resolve to
+
+ Outputs: Returns true if able to resolve each of the expressions down
+          to one or more functions.
+
+ Purpose: To resolve a collection of expressions to the specific function
+          calls they can be. Returns a collection if and only if all of
+          them can be resolved.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::try_resolve_function_calls(
+  const expressionst &exprs, functionst &out_functions)
+{
+  for(const exprt &value : exprs)
+  {
+    functionst potential_out_functions;
+    bool resolved_value=
+      try_resolve_function_call(value, potential_out_functions);
+
+    if(resolved_value)
+    {
+      out_functions.insert(
+        potential_out_functions.begin(),
+        potential_out_functions.end());
+    }
+    else
+    {
+      LOG("Could not resolve expression in array", value);
+      return false;
+    }
+  }
+  return true;
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::try_resolve_index_of_function_call
+
+  Inputs:
+   index_expr - The index expression to resolve to possible function calls
+   out_functions - The functions this expression could be
+
+ Outputs: Returns true if it was able to resolve the index expression to some
+          specific functions. If this is the case, out_functions will contain
+          the possible functions.
+
+ Purpose: To resolve an expression to the specific function calls it can
+          be. Specifically, this function deals with index expressions
+          where it squashes its array and squash its index
+          If we can get a precise number for the index, we
+          try_resolve_function_call on its value otherwise
+          try_resolve_function_call on each and return the union of them all
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::try_resolve_index_of_function_call(
+  const index_exprt &index_expr, functionst &out_functions)
+{
+  expressionst potential_array_values;
+  bool array_const;
+  bool resolved=
+    try_resolve_index_of(index_expr, potential_array_values, array_const);
+
+  if(!resolved)
+  {
+    LOG("Could not resolve array", index_expr);
+    return false;
+  }
+
+  if(!array_const)
+  {
+    LOG("Array not const", index_expr);
+    return false;
+  }
+
+  return try_resolve_function_calls(potential_array_values, out_functions);
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::try_resolve_member_function_call
+
+  Inputs:
+   member_expr - The member expression to resolve to possible function calls
+   out_functions - The functions this expression could be
+
+ Outputs: Returns true if it was able to resolve the member expression to some
+          specific functions. If this is the case, out_functions will contain
+          the possible functions.
+
+ Purpose: To resolve an expression to the specific function calls it can
+          be. Specifically, this function deals with member expressions
+          by using try_resolve_member and then recursing on its value.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::try_resolve_member_function_call(
+  const member_exprt &member_expr, functionst &out_functions)
+{
+  expressionst potential_component_values;
+  bool struct_const;
+  bool resolved=
+    try_resolve_member(member_expr, potential_component_values, struct_const);
+
+  if(!resolved)
+  {
+    LOG("Could not resolve struct", member_expr);
+    return false;
+  }
+
+  if(!struct_const)
+  {
+    LOG("Struct was not const so can't resolve values on it", member_expr);
+    return false;
+  }
+
+  return try_resolve_function_calls(potential_component_values, out_functions);
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::try_resolve_address_of_function_call
+
+  Inputs:
+   address_expr - The address_of expression to resolve to possible function
+                  calls
+   out_functions - The functions this expression could be
+
+ Outputs: Returns true if it was able to resolve the address_of expression to
+          some specific functions. If this is the case, out_functions will
+          contain the possible functions.
+
+ Purpose: To resolve an expression to the specific function calls it can
+          be. Specifically, this function deals with address_of expressions.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::try_resolve_address_of_function_call(
+  const address_of_exprt &address_expr, functionst &out_functions)
+{
+  bool resolved=
+    try_resolve_function_call(address_expr.object(), out_functions);
+  if(!resolved)
+  {
+    LOG("Failed to resolve address of", address_expr);
+  }
+  return resolved;
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::try_resolve_dereference_function_call
+
+  Inputs:
+   deref_expr - The dereference expression to resolve to possible function calls
+   out_functions - The functions this expression could be
+
+ Outputs: Returns true if it was able to resolve the dereference expression to
+          some specific functions. If this is the case, out_functions will
+          contain the possible functions.
+
+ Purpose: To resolve an expression to the specific function calls it can
+          be. Specifically, this function deals with dereference expressions
+          by using try_resolve_dereferebce and then recursing on its value.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::try_resolve_dereference_function_call(
+  const dereference_exprt &deref_expr, functionst &out_functions)
+{
+  expressionst potential_deref_values;
+  bool deref_const;
+  bool resolved=
+    try_resolve_dereference(deref_expr, potential_deref_values, deref_const);
+
+  if(!resolved)
+  {
+    LOG("Failed to squash dereference", deref_expr);
+    return false;
+  }
+
+  if(!deref_const)
+  {
+    LOG("Dereferenced value was not const so can't dereference", deref_expr);
+    return false;
+  }
+
+  return try_resolve_function_calls(potential_deref_values, out_functions);
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::try_resolve_typecast_function_call
+
+  Inputs:
+   typecast_expr - The typecast expression to resolve to possible function calls
+   out_functions - The functions this expression could be
+
+ Outputs: Returns true if it was able to resolve the typecast expression to
+          some specific functions. If this is the case, out_functions will
+          contain the possible functions.
+
+ Purpose: To resolve an expression to the specific function calls it can
+          be. Specifically, this function deals with typecast expressions
+          by looking at the type cast values.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::try_resolve_typecast_function_call(
+  const typecast_exprt &typecast_expr, functionst &out_functions)
+{
+  // We simply ignore typecasts and assume they are valid
+  // I thought simplify_expr would deal with this, but for example
+  // a cast from a 32 bit width int to a 64bit width int it doesn't seem
+  // to allow
+  functionst typecast_values;
+  bool resolved=
+    try_resolve_function_call(typecast_expr.op(), typecast_values);
+
+  if(resolved)
+  {
+    out_functions.insert(typecast_values.begin(), typecast_values.end());
+    return true;
+  }
+  else
+  {
+    LOG("Failed to squash typecast", typecast_expr);
+    return false;
+  }
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::try_resolve_expression
+
+  Inputs:
+   expr - The expression to try and squash
+   out_resolved_expression - The squashed version of this expression
+   out_is_const - Is the squashed expression constant
+
+ Outputs: Returns true providing the squashing went OK (note it
+          may not have squashed anything). The out_resolved_expression will in
+          this case be all the possible squashed versions of the supplied
+          expression.
+          The out_is_const will return whether the squashed value is suitably
+          const (e.g. if we squashed a struct access, was the struct const).
+
+ Purpose: To squash various expr types to simplify the expression.
+          ID_index -> dig to find ID_array and get the values out of it
+          ID_member -> dig to find ID_struct and extract the component value
+          ID_dereference -> dig to find ID_address_of and extract the value
+          ID_typecast -> return the value
+          ID_symbol -> return false, const symbols are squashed first and
+                       non const symbols cannot be squashed
+          Everything else -> unchanged
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::try_resolve_expression(
+  const exprt &expr, expressionst &out_resolved_expression, bool &out_is_const)
+{
+  exprt simplified_expr=simplify_expr(expr, ns);
+  bool resolved;
+  expressionst resolved_expressions;
+  bool is_resolved_expression_const;
+  if(simplified_expr.id()==ID_index)
+  {
+    const index_exprt &index_expr=to_index_expr(simplified_expr);
+    resolved=
+      try_resolve_index_of(
+        index_expr, resolved_expressions, is_resolved_expression_const);
+  }
+  else if(simplified_expr.id()==ID_member)
+  {
+    const member_exprt &member_expr=to_member_expr(simplified_expr);
+    resolved=try_resolve_member(
+      member_expr, resolved_expressions, is_resolved_expression_const);
+  }
+  else if(simplified_expr.id()==ID_dereference)
+  {
+    const dereference_exprt &deref=to_dereference_expr(simplified_expr);
+    resolved=
+      try_resolve_dereference(
+        deref, resolved_expressions, is_resolved_expression_const);
+  }
+  else if(simplified_expr.id()==ID_typecast)
+  {
+    typecast_exprt typecast_expr=to_typecast_expr(simplified_expr);
+    resolved=
+      try_resolve_typecast(
+        typecast_expr, resolved_expressions, is_resolved_expression_const);
+  }
+  else if(simplified_expr.id()==ID_symbol)
+  {
+    LOG("Non const symbol will not be squashed", simplified_expr);
+    resolved=false;
+  }
+  else
+  {
+    resolved_expressions.push_back(simplified_expr);
+    is_resolved_expression_const=is_const_expression(simplified_expr);
+    resolved=true;
+  }
+
+  if(resolved)
+  {
+    out_resolved_expression.insert(
+      out_resolved_expression.end(),
+      resolved_expressions.begin(),
+      resolved_expressions.end());
+    out_is_const=is_resolved_expression_const;
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::try_resolve_index_value
+
+  Inputs:
+   expr - The expression of the index of the index expression (e.g.
+          index_exprt::index())
+   out_array_index - The constant value the index takes
+
+ Outputs: Returns true if was able to find a constant value for the index
+          expression. If true, then out_array_index will be the index within
+          the array that the function pointer is pointing to.
+
+ Purpose: Given an index into an array, resolve, if possible, the index
+          that is being accessed. This deals with symbols and typecasts to
+          constant values.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::try_resolve_index_value(
+  const exprt &expr, mp_integer &out_array_index)
+{
+  expressionst index_value_expressions;
+  bool is_const=false;
+  bool resolved=try_resolve_expression(expr, index_value_expressions, is_const);
+  if(resolved)
+  {
+    if(index_value_expressions.size()==1 &&
+       index_value_expressions.front().id()==ID_constant)
+    {
+      const constant_exprt &constant_expr=
+        to_constant_expr(index_value_expressions.front());
+      mp_integer array_index;
+      bool errors=to_integer(constant_expr, array_index);
+      if(!errors)
+      {
+        out_array_index=array_index;
+      }
+      return !errors;
+    }
+    else
+    {
+      return false;
+    }
+  }
+  else
+  {
+    return false;
+  }
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::try_resolve_index_of
+
+  Inputs:
+   index_expr - The index expression to  to resolve
+   out_expressions - The expressions this expression could be
+   out_is_const - Is the squashed expression constant
+
+ Outputs: Returns true if it was able to squash the index expression
+          If this is the case, out_expressions will contain
+          the possible values this index_of could return
+          The out_is_const will return whether either the array itself
+          is const, or the values of the array are const.
+
+ Purpose: To squash an index access by first finding the array it is accessing
+          Then if the index can be resolved, return the squashed value. If
+          the index can't be determined then squash each value in the array
+          and return them all.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::try_resolve_index_of(
+  const index_exprt &index_expr,
+  expressionst &out_expressions,
+  bool &out_is_const)
+{
+  // Get the array(s) it belongs to
+  expressionst potential_array_exprs;
+  bool array_const=false;
+  bool resolved_array=
+    try_resolve_expression(
+      index_expr.array(),
+      potential_array_exprs,
+      array_const);
+
+  if(resolved_array)
+  {
+    bool all_possible_const=true;
+    for(const exprt &potential_array_expr : potential_array_exprs)
+    {
+      all_possible_const=
+        all_possible_const &&
+        is_const_type(potential_array_expr.type().subtype());
+
+      if(potential_array_expr.id()==ID_array)
+      {
+        // Get the index if we can
+        mp_integer value;
+        if(try_resolve_index_value(index_expr.index(), value))
+        {
+          expressionst array_out_functions;
+          const exprt &func_expr=
+            potential_array_expr.operands()[integer2size_t(value)];
+          bool value_const=false;
+          bool resolved_value=
+            try_resolve_expression(func_expr, array_out_functions, value_const);
+
+          if(resolved_value)
+          {
+            out_expressions.insert(
+              out_expressions.end(),
+              array_out_functions.begin(),
+              array_out_functions.end());
+          }
+          else
+          {
+            LOG("Failed to resolve array value", func_expr);
+            return false;
+          }
+        }
+        else
+        {
+          // We don't know what index it is,
+          // but we know the value is from the array
+          for(const exprt &array_entry : potential_array_expr.operands())
+          {
+            expressionst array_contents;
+            bool is_entry_const;
+            bool resolved_value=
+              try_resolve_expression(
+                array_entry, array_contents, is_entry_const);
+
+            if(!resolved_value)
+            {
+              LOG("Failed to resolve array value", array_entry);
+              return false;
+            }
+
+            for(const exprt &resolved_array_entry : array_contents)
+            {
+              if(!resolved_array_entry.is_zero())
+              {
+                out_expressions.push_back(resolved_array_entry);
+              }
+            }
+          }
+        }
+      }
+      else
+      {
+        LOG(
+          "Squashing index of did not result in an array",
+          potential_array_expr);
+        return false;
+      }
+    }
+
+    out_is_const=all_possible_const || array_const;
+    return true;
+  }
+  else
+  {
+    LOG("Failed to squash index of to array expression", index_expr);
+    return false;
+  }
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::try_resolve_member
+
+  Inputs:
+   member_expr - The member expression to resolve.
+   out_expressions - The expressions this component could be
+   out_is_const - Is the squashed expression constant
+
+ Outputs: Returns true if it was able to squash the member expression
+          If this is the case, out_expressions will contain
+          the possible values this member could return
+          The out_is_const will return whether the struct
+          is const.
+
+ Purpose: To squash an member access by first finding the struct it is accessing
+          Then return the squashed value of the relevant component.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::try_resolve_member(
+  const member_exprt &member_expr,
+  expressionst &out_expressions,
+  bool &out_is_const)
+{
+  expressionst potential_structs;
+  bool is_struct_const;
+
+  // Get the struct it belongs to
+  bool resolved_struct=
+    try_resolve_expression(
+      member_expr.compound(), potential_structs, is_struct_const);
+  if(resolved_struct)
+  {
+    for(const exprt &potential_struct : potential_structs)
+    {
+      if(potential_struct.id()==ID_struct)
+      {
+        struct_exprt struct_expr=to_struct_expr(potential_struct);
+        const exprt &component_value=
+          get_component_value(struct_expr, member_expr);
+        expressionst resolved_expressions;
+        bool component_const=false;
+        bool resolved=
+          try_resolve_expression(
+            component_value, resolved_expressions, component_const);
+        if(resolved)
+        {
+          out_expressions.insert(
+            out_expressions.end(),
+            resolved_expressions.begin(),
+            resolved_expressions.end());
+        }
+        else
+        {
+          LOG("Could not resolve component value", component_value);
+          return false;
+        }
+      }
+      else
+      {
+        LOG(
+          "Squashing member access did not resolve in a struct",
+          potential_struct);
+        return false;
+      }
+    }
+    out_is_const=is_struct_const;
+    return true;
+  }
+  else
+  {
+    LOG("Failed to squash struct access", member_expr);
+    return false;
+  }
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::try_resolve_dereference
+
+  Inputs:
+   deref_expr - The dereference expression to resolve.
+   out_expressions - The expressions this dereference could be
+   out_is_const - Is the squashed expression constant
+
+ Outputs: Returns true if it was able to squash the dereference expression
+          If this is the case, out_expressions will contain
+          the possible values this dereference could return
+          The out_is_const will return whether the object that gets
+          dereferenced is constant.
+
+ Purpose: To squash a dereference access by first finding the address_of
+          the dereference is dereferencing.
+          Then return the squashed value of the relevant component.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::try_resolve_dereference(
+  const dereference_exprt &deref_expr,
+  expressionst &out_expressions,
+  bool &out_is_const)
+{
+  // We had a pointer, we need to check both the pointer
+  // type can't be changed, and what it what pointing to
+  // can't be changed
+  expressionst pointer_values;
+  bool pointer_const;
+  bool resolved=
+    try_resolve_expression(deref_expr.pointer(), pointer_values, pointer_const);
+  if(resolved && pointer_const)
+  {
+    bool all_objects_const=true;
+    for(const exprt &pointer_val : pointer_values)
+    {
+      if(pointer_val.id()==ID_address_of)
+      {
+        address_of_exprt address_expr=to_address_of_expr(pointer_val);
+        bool object_const=false;
+        expressionst out_object_values;
+        bool resolved=
+          try_resolve_expression(
+            address_expr.object(), out_object_values, object_const);
+
+        if(resolved)
+        {
+          out_expressions.insert(
+            out_expressions.end(),
+            out_object_values.begin(),
+            out_object_values.end());
+
+          all_objects_const&=object_const;
+        }
+        else
+        {
+          LOG("Failed to resolve value of a dereference", address_expr);
+        }
+      }
+      else
+      {
+        LOG(
+          "Squashing dereference did not result in an address", pointer_val);
+        return false;
+      }
+    }
+    out_is_const=all_objects_const;
+    return true;
+  }
+  else
+  {
+    if(!resolved)
+    {
+      LOG("Failed to resolve pointer of dereference", deref_expr);
+    }
+    else if(!pointer_const)
+    {
+      LOG("Pointer value not const so can't squash", deref_expr);
+    }
+    return false;
+  }
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::try_resolve_dereference
+
+  Inputs:
+   typecast_expr - The typecast expression to resolve.
+   out_expressions - The expressions this typecast could be
+   out_is_const - Is the squashed expression constant
+
+ Outputs: Returns true if it was able to squash the typecast expression
+          If this is the case, out_expressions will contain
+          the possible values after removing the typecast.
+
+ Purpose: To squash a typecast access.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::try_resolve_typecast(
+  const typecast_exprt &typecast_expr,
+  expressionst &out_expressions,
+  bool &out_is_const)
+{
+  expressionst typecast_values;
+  bool typecast_const;
+  bool resolved=
+    try_resolve_expression(
+      typecast_expr.op(), typecast_values, typecast_const);
+
+  if(resolved)
+  {
+    out_expressions.insert(
+      out_expressions.end(),
+      typecast_values.begin(),
+      typecast_values.end());
+    out_is_const=typecast_const;
+    return true;
+  }
+  else
+  {
+    LOG("Could not resolve typecast value", typecast_expr);
+    return false;
+  }
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::is_expression_const
+
+  Inputs:
+   expression - The expression to check
+
+ Outputs: Returns true if the type of the expression is constant.
+
+ Purpose: To evaluate the const-ness of the expression type.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::is_const_expression(
+  const exprt &expression) const
+{
+  return is_const_type(expression.type());
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::is_type_const
+
+  Inputs:
+   type - The type to check
+
+ Outputs: Returns true if the type has ID_C_constant or is an array
+          since arrays are implicitly const in C.
+
+ Purpose: To evaluate the const-ness of the type.
+
+\*******************************************************************/
+
+bool remove_const_function_pointerst::is_const_type(const typet &type) const
+{
+  c_qualifierst qualifers(type);
+  if(type.id()==ID_array)
+  {
+    c_qualifierst array_type_qualifers(type.subtype());
+    return qualifers.is_constant || array_type_qualifers.is_constant;
+  }
+  else
+  {
+    return qualifers.is_constant;
+  }
+}
+
+/*******************************************************************\
+
+Function: remove_const_function_pointerst::get_component_value
+
+  Inputs:
+   struct_expr - The expression of the structure being accessed
+   member_expr - The expression saying which component is being accessed
+
+ Outputs: Returns the value of a specific component for a given struct
+          expression.
+
+ Purpose: To extract the value of the specific component within a struct
+
+\*******************************************************************/
+
+exprt remove_const_function_pointerst::get_component_value(
+  const struct_exprt &struct_expr, const member_exprt &member_expr)
+{
+  const struct_typet &struct_type=to_struct_type(ns.follow(struct_expr.type()));
+  size_t component_number=
+    struct_type.component_number(member_expr.get_component_name());
+
+  return struct_expr.operands()[component_number];
+}
diff --git a/src/goto-programs/remove_const_function_pointers.h b/src/goto-programs/remove_const_function_pointers.h
new file mode 100644
index 00000000000..6516fb6ec64
--- /dev/null
+++ b/src/goto-programs/remove_const_function_pointers.h
@@ -0,0 +1,105 @@
+/*******************************************************************\
+
+Module: Goto Programs
+
+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 "goto_model.h"
+#include 
+#include 
+#include 
+
+
+class remove_const_function_pointerst:public messaget
+{
+public:
+  typedef std::unordered_set functionst;
+  typedef std::list expressionst;
+  remove_const_function_pointerst(
+    message_handlert &message_handler,
+    const exprt &base_expression,
+    const namespacet &ns,
+    const symbol_tablet &symbol_table);
+
+  bool operator()(functionst &out_functions);
+
+private:
+  exprt replace_const_symbols(const exprt &expression) const;
+  exprt resolve_symbol(const symbol_exprt &symbol_expr) const;
+
+  // recursive functions for dealing with the function pointer
+  bool try_resolve_function_call(const exprt &expr, functionst &out_functions);
+
+  bool try_resolve_function_calls(
+    const expressionst &exprs, functionst &out_functions);
+
+  bool try_resolve_index_of_function_call(
+    const index_exprt &index_expr, functionst &out_functions);
+
+  bool try_resolve_member_function_call(
+    const member_exprt &member_expr, functionst &out_functions);
+
+  bool try_resolve_address_of_function_call(
+    const address_of_exprt &address_expr, functionst &out_functions);
+
+  bool try_resolve_dereference_function_call(
+    const dereference_exprt &deref_expr, functionst &out_functions);
+
+  bool try_resolve_typecast_function_call(
+    const typecast_exprt &typecast_expr, functionst &out_functions);
+
+  // recursive functions for dealing with the auxiliary elements
+  bool try_resolve_expression(
+    const exprt &expr,
+    expressionst &out_resolved_expression,
+    bool &out_is_const);
+
+  bool try_resolve_index_of(
+    const index_exprt &index_expr,
+    expressionst &out_expressions,
+    bool &out_is_const);
+
+  bool try_resolve_member(
+    const member_exprt &member_expr,
+    expressionst &out_expressions,
+    bool &out_is_const);
+
+  bool try_resolve_dereference(
+    const dereference_exprt &deref_expr,
+    expressionst &out_expressions,
+    bool &out_is_const);
+
+  bool try_resolve_typecast(
+    const typecast_exprt &typecast_expr,
+    expressionst &out_expressions,
+    bool &out_is_const);
+
+  bool is_const_expression(const exprt &expression) const;
+  bool is_const_type(const typet &type) const;
+
+  bool try_resolve_index_value(
+    const exprt &index_value_expr, mp_integer &out_array_index);
+
+  exprt get_component_value(
+    const struct_exprt &struct_expr, const member_exprt &member_expr);
+
+  const exprt original_expression;
+  const namespacet &ns;
+  const symbol_tablet &symbol_table;
+};
+
+#define OPT_REMOVE_CONST_FUNCTION_POINTERS \
+  "(remove-const-function-pointers)"
+
+#define HELP_REMOVE_CONST_FUNCTION_POINTERS \
+  " --remove-const-function-pointers    Remove function pointers that are constant or constant part of an array\n" // NOLINT(*)
+
+
+#endif // CPROVER_GOTO_PROGRAMS_REMOVE_CONST_FUNCTION_POINTERS_H
diff --git a/src/goto-programs/remove_function_pointers.cpp b/src/goto-programs/remove_function_pointers.cpp
index 3893729a1e1..c67c834b2ce 100644
--- a/src/goto-programs/remove_function_pointers.cpp
+++ b/src/goto-programs/remove_function_pointers.cpp
@@ -14,12 +14,17 @@ Author: Daniel Kroening, kroening@kroening.com
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include 
 
 #include "remove_skip.h"
 #include "remove_function_pointers.h"
 #include "compute_called_functions.h"
+#include "remove_const_function_pointers.h"
 
 /*******************************************************************\
 
@@ -29,12 +34,14 @@ Author: Daniel Kroening, kroening@kroening.com
 
 \*******************************************************************/
 
-class remove_function_pointerst
+class remove_function_pointerst:public messaget
 {
 public:
   remove_function_pointerst(
+    message_handlert &_message_handler,
     symbol_tablet &_symbol_table,
     bool _add_safety_assertion,
+    bool only_resolve_const_fps,
     const goto_functionst &goto_functions);
 
   void operator()(goto_functionst &goto_functions);
@@ -46,6 +53,14 @@ class remove_function_pointerst
   symbol_tablet &symbol_table;
   bool add_safety_assertion;
 
+  // We can optionally halt the FP removal if we aren't able to use
+  // remove_const_function_pointerst to sucessfully narrow to a small
+  // subset of possible functions and just leave the function pointer
+  // as it is.
+  // This can be activated in goto-instrument using
+  // --remove-const-function-pointers instead of --remove-function-pointers
+  bool only_resolve_const_fps;
+
   void remove_function_pointer(
     goto_programt &goto_program,
     goto_programt::targett target);
@@ -92,12 +107,15 @@ Function: remove_function_pointerst::remove_function_pointerst
 \*******************************************************************/
 
 remove_function_pointerst::remove_function_pointerst(
+  message_handlert &_message_handler,
   symbol_tablet &_symbol_table,
-  bool _add_safety_assertion,
+  bool _add_safety_assertion, bool only_resolve_const_fps,
   const goto_functionst &goto_functions):
+  messaget(_message_handler),
   ns(_symbol_table),
   symbol_table(_symbol_table),
-  add_safety_assertion(_add_safety_assertion)
+  add_safety_assertion(_add_safety_assertion),
+  only_resolve_const_fps(only_resolve_const_fps)
 {
   compute_address_taken_in_symbols(address_taken);
   compute_address_taken_functions(goto_functions, address_taken);
@@ -338,41 +356,71 @@ void remove_function_pointerst::remove_function_pointer(
   assert(function.id()==ID_dereference);
   assert(function.operands().size()==1);
 
-  const exprt &pointer=function.op0();
+  bool found_functions;
 
-  // Is this simple?
-  if(pointer.id()==ID_address_of &&
-     to_address_of_expr(pointer).object().id()==ID_symbol)
+  const exprt &pointer=function.op0();
+  remove_const_function_pointerst::functionst functions;
+  does_remove_constt const_removal_check(goto_program, ns);
+  if(const_removal_check())
   {
-    to_code_function_call(target->code).function()=
-      to_address_of_expr(pointer).object();
-    return;
+    warning() << "Cast from const to non-const pointer found, only worst case"
+              << " function pointer removal will be done." << eom;
+    found_functions=false;
   }
+  else
+  {
+    remove_const_function_pointerst fpr(
+    get_message_handler(), pointer, ns, symbol_table);
 
-  typedef std::list functionst;
-  functionst functions;
+    found_functions=fpr(functions);
 
-  bool return_value_used=code.lhs().is_not_nil();
+    // Either found_functions is true therefore the functions should not
+    // be empty
+    // Or found_functions is false therefore the functions should be empty
+    assert(found_functions != functions.empty());
 
-  // get all type-compatible functions
-  // whose address is ever taken
-  for(const auto &t : type_map)
+    if(functions.size()==1)
+    {
+      to_code_function_call(target->code).function()=*functions.cbegin();
+      return;
+    }
+  }
+
+  if(!found_functions)
   {
-    // address taken?
-    if(address_taken.find(t.first)==address_taken.end())
-      continue;
+    if(only_resolve_const_fps)
+    {
+      // If this mode is enabled, we only remove function pointers
+      // that we can resolve either to an exact funciton, or an exact subset
+      // (e.g. a variable index in a constant array).
+      // Since we haven't found functions, we would now resort to
+      // replacing the function pointer with any function with a valid signature
+      // Since we don't want to do that, we abort.
+      return;
+    }
+
+    bool return_value_used=code.lhs().is_not_nil();
 
-    // type-compatible?
-    if(!is_type_compatible(return_value_used, call_type, t.second))
-      continue;
+    // get all type-compatible functions
+    // whose address is ever taken
+    for(const auto &t : type_map)
+    {
+      // address taken?
+      if(address_taken.find(t.first)==address_taken.end())
+        continue;
+
+      // type-compatible?
+      if(!is_type_compatible(return_value_used, call_type, t.second))
+        continue;
 
-    if(t.first=="pthread_mutex_cleanup")
-      continue;
+      if(t.first=="pthread_mutex_cleanup")
+        continue;
 
-    symbol_exprt expr;
-    expr.type()=t.second;
-    expr.set_identifier(t.first);
-    functions.push_back(expr);
+      symbol_exprt expr;
+      expr.type()=t.second;
+      expr.set_identifier(t.first);
+        functions.insert(expr);
+    }
   }
 
   // the final target is a skip
@@ -539,14 +587,20 @@ Function: remove_function_pointers
 
 \*******************************************************************/
 
-bool remove_function_pointers(
+bool remove_function_pointers(message_handlert &_message_handler,
   symbol_tablet &symbol_table,
   const goto_functionst &goto_functions,
   goto_programt &goto_program,
-  bool add_safety_assertion)
+  bool add_safety_assertion,
+  bool only_remove_const_fps)
 {
   remove_function_pointerst
-    rfp(symbol_table, add_safety_assertion, goto_functions);
+    rfp(
+      _message_handler,
+      symbol_table,
+      add_safety_assertion,
+      only_remove_const_fps,
+      goto_functions);
 
   return rfp.remove_function_pointers(goto_program);
 }
@@ -564,12 +618,19 @@ Function: remove_function_pointers
 \*******************************************************************/
 
 void remove_function_pointers(
+  message_handlert &_message_handler,
   symbol_tablet &symbol_table,
   goto_functionst &goto_functions,
-  bool add_safety_assertion)
+  bool add_safety_assertion,
+  bool only_remove_const_fps)
 {
   remove_function_pointerst
-    rfp(symbol_table, add_safety_assertion, goto_functions);
+    rfp(
+      _message_handler,
+      symbol_table,
+      add_safety_assertion,
+      only_remove_const_fps,
+      goto_functions);
 
   rfp(goto_functions);
 }
@@ -586,11 +647,15 @@ Function: remove_function_pointers
 
 \*******************************************************************/
 
-void remove_function_pointers(
+void remove_function_pointers(message_handlert &_message_handler,
   goto_modelt &goto_model,
-  bool add_safety_assertion)
+  bool add_safety_assertion,
+  bool only_remove_const_fps)
 {
   remove_function_pointers(
-    goto_model.symbol_table, goto_model.goto_functions,
-    add_safety_assertion);
+    _message_handler,
+    goto_model.symbol_table,
+    goto_model.goto_functions,
+    add_safety_assertion,
+    only_remove_const_fps);
 }
diff --git a/src/goto-programs/remove_function_pointers.h b/src/goto-programs/remove_function_pointers.h
index 6f1f26984df..e8eea37ea75 100644
--- a/src/goto-programs/remove_function_pointers.h
+++ b/src/goto-programs/remove_function_pointers.h
@@ -12,22 +12,29 @@ Date: June 2003
 #define CPROVER_GOTO_PROGRAMS_REMOVE_FUNCTION_POINTERS_H
 
 #include "goto_model.h"
+#include 
 
 // remove indirect function calls
 // and replace by case-split
 void remove_function_pointers(
+  message_handlert &_message_handler,
   goto_modelt &goto_model,
-  bool add_safety_assertion);
+  bool add_safety_assertion,
+  bool only_remove_const_fps=false);
 
 void remove_function_pointers(
+  message_handlert &_message_handler,
   symbol_tablet &symbol_table,
   goto_functionst &goto_functions,
-  bool add_safety_assertion);
+  bool add_safety_assertion,
+  bool only_remove_const_fps=false);
 
 bool remove_function_pointers(
+  message_handlert &_message_handler,
   symbol_tablet &symbol_table,
   const goto_functionst &goto_functions,
   goto_programt &goto_program,
-  bool add_safety_assertion);
+  bool add_safety_assertion,
+  bool only_remove_const_fps=false);
 
 #endif // CPROVER_GOTO_PROGRAMS_REMOVE_FUNCTION_POINTERS_H
diff --git a/src/goto-programs/remove_returns.cpp b/src/goto-programs/remove_returns.cpp
index b3afbf967fc..9ca6554275c 100644
--- a/src/goto-programs/remove_returns.cpp
+++ b/src/goto-programs/remove_returns.cpp
@@ -269,6 +269,46 @@ void remove_returns(goto_modelt &goto_model)
 
 /*******************************************************************\
 
+Function: original_return_type
+
+Inputs:
+
+Outputs:
+
+Purpose:
+
+\*******************************************************************/
+
+code_typet original_return_type(
+  const symbol_tablet &symbol_table,
+  const irep_idt &function_id)
+{
+  code_typet type;
+  type.make_nil();
+
+  // do we have X#return_value?
+  std::string rv_name=id2string(function_id)+RETURN_VALUE_SUFFIX;
+
+  symbol_tablet::symbolst::const_iterator rv_it=
+    symbol_table.symbols.find(rv_name);
+
+  if(rv_it!=symbol_table.symbols.end())
+  {
+    // look up the function symbol
+    symbol_tablet::symbolst::const_iterator s_it=
+      symbol_table.symbols.find(function_id);
+
+    assert(s_it!=symbol_table.symbols.end());
+
+    type=to_code_type(s_it->second.type);
+    type.return_type()=rv_it->second.type;
+  }
+
+  return type;
+}
+
+/*******************************************************************\
+
 Function: remove_returnst::restore_returns
 
 Inputs:
@@ -301,7 +341,7 @@ bool remove_returnst::restore_returns(
   symbolt &function_symbol=s_it->second;
 
   // restore the return type
-  f_it->second.type.return_type()=rv_it->second.type;
+  f_it->second.type=original_return_type(symbol_table, function_id);
   function_symbol.type=f_it->second.type;
 
   // remove the return_value symbol from the symbol_table
diff --git a/src/goto-programs/remove_returns.h b/src/goto-programs/remove_returns.h
index 3f68d3e89e2..453d8a7be7f 100644
--- a/src/goto-programs/remove_returns.h
+++ b/src/goto-programs/remove_returns.h
@@ -26,4 +26,8 @@ void remove_returns(goto_modelt &);
 // reverse the above operations
 void restore_returns(symbol_tablet &, goto_functionst &);
 
+code_typet original_return_type(
+  const symbol_tablet &symbol_table,
+  const irep_idt &function_id);
+
 #endif // CPROVER_GOTO_PROGRAMS_REMOVE_RETURNS_H
diff --git a/src/goto-programs/remove_virtual_functions.cpp b/src/goto-programs/remove_virtual_functions.cpp
index c93b50a2500..fde2f5f8405 100644
--- a/src/goto-programs/remove_virtual_functions.cpp
+++ b/src/goto-programs/remove_virtual_functions.cpp
@@ -57,8 +57,11 @@ class remove_virtual_functionst
   typedef std::vector functionst;
   void get_functions(const exprt &, functionst &);
   void get_child_functions_rec(
-    const irep_idt &, const symbol_exprt &,
-    const irep_idt &, functionst &) const;
+    const irep_idt &,
+    const symbol_exprt &,
+    const irep_idt &,
+    functionst &,
+    std::set &visited) const;
   exprt get_method(
     const irep_idt &class_id,
     const irep_idt &component_name) const;
@@ -254,7 +257,8 @@ void remove_virtual_functionst::get_child_functions_rec(
   const irep_idt &this_id,
   const symbol_exprt &last_method_defn,
   const irep_idt &component_name,
-  functionst &functions) const
+  functionst &functions,
+  std::set &visited) const
 {
   auto findit=class_hierarchy.class_map.find(this_id);
   if(findit==class_hierarchy.class_map.end())
@@ -262,6 +266,8 @@ void remove_virtual_functionst::get_child_functions_rec(
 
   for(const auto &child : findit->second.children)
   {
+    if(!visited.insert(child).second)
+      continue;
     exprt method=get_method(child, component_name);
     functiont function(child);
     if(method.is_not_nil())
@@ -279,7 +285,8 @@ void remove_virtual_functionst::get_child_functions_rec(
       child,
       function.symbol_expr,
       component_name,
-      functions);
+      functions,
+      visited);
   }
 }
 
@@ -333,11 +340,13 @@ void remove_virtual_functionst::get_functions(
   }
 
   // iterate over all children, transitively
+  std::set visited;
   get_child_functions_rec(
     class_id,
     root_function.symbol_expr,
     component_name,
-    functions);
+    functions,
+    visited);
 
   if(root_function.symbol_expr!=symbol_exprt())
     functions.push_back(root_function);
diff --git a/src/goto-programs/show_goto_functions_json.cpp b/src/goto-programs/show_goto_functions_json.cpp
index 1f61e30d2f6..47a19e0662a 100644
--- a/src/goto-programs/show_goto_functions_json.cpp
+++ b/src/goto-programs/show_goto_functions_json.cpp
@@ -67,7 +67,7 @@ json_objectt show_goto_functions_jsont::convert(
     json_function["isBodyAvailable"]=
       jsont::json_boolean(function.body_available());
     bool is_internal=(has_prefix(id2string(function_name), CPROVER_PREFIX) ||
-                      function_name==ID__start);
+                      function_name==goto_functions.entry_point());
     json_function["isInternal"]=jsont::json_boolean(is_internal);
 
     if(function.body_available())
diff --git a/src/goto-programs/show_goto_functions_xml.cpp b/src/goto-programs/show_goto_functions_xml.cpp
index a5d1c9d5dd4..7ccdd71a4ff 100644
--- a/src/goto-programs/show_goto_functions_xml.cpp
+++ b/src/goto-programs/show_goto_functions_xml.cpp
@@ -80,7 +80,7 @@ xmlt show_goto_functions_xmlt::convert(
     xml_function.set_attribute_bool(
       "is_body_available", function.body_available());
     bool is_internal=(has_prefix(id2string(function_name), CPROVER_PREFIX) ||
-                      function_name==ID__start);
+                      function_name==goto_functions.entry_point());
     xml_function.set_attribute_bool("is_internal", is_internal);
 
     if(function.body_available())
diff --git a/src/goto-symex/build_goto_trace.cpp b/src/goto-symex/build_goto_trace.cpp
index 1cbb442497a..081fcbe55d3 100644
--- a/src/goto-symex/build_goto_trace.cpp
+++ b/src/goto-symex/build_goto_trace.cpp
@@ -238,11 +238,17 @@ void build_goto_trace(
 
   mp_integer current_time=0;
 
+  const goto_trace_stept *end_ptr=nullptr;
+  bool end_step_seen=false;
+
   for(symex_target_equationt::SSA_stepst::const_iterator
       it=target.SSA_steps.begin();
-      it!=end_step;
+      it!=target.SSA_steps.end();
       it++)
   {
+    if(it==end_step)
+      end_step_seen=true;
+
     const symex_target_equationt::SSA_stept &SSA_step=*it;
 
     if(prop_conv.l_get(SSA_step.guard_literal)!=tvt(true))
@@ -301,6 +307,8 @@ void build_goto_trace(
     goto_tracet::stepst &steps=time_map[current_time];
     steps.push_back(goto_trace_stept());
     goto_trace_stept &goto_trace_step=steps.back();
+    if(!end_step_seen)
+      end_ptr=&goto_trace_step;
 
     goto_trace_step.thread_nr=SSA_step.source.thread_nr;
     goto_trace_step.pc=SSA_step.source.pc;
@@ -369,6 +377,17 @@ void build_goto_trace(
   for(auto &t_it : time_map)
     goto_trace.steps.splice(goto_trace.steps.end(), t_it.second);
 
+  // cut off the trace at the desired end
+  for(goto_tracet::stepst::iterator
+      s_it1=goto_trace.steps.begin();
+      s_it1!=goto_trace.steps.end();
+      ++s_it1)
+    if(end_step_seen && end_ptr==&(*s_it1))
+    {
+      goto_trace.trim_after(s_it1);
+      break;
+    }
+
   // produce the step numbers
   unsigned step_nr=0;
 
@@ -404,7 +423,7 @@ void build_goto_trace(
       s_it1++)
     if(s_it1->is_assert() && !s_it1->cond_value)
     {
-      goto_trace.steps.erase(++s_it1, goto_trace.steps.end());
+      goto_trace.trim_after(s_it1);
       break;
     }
 }
diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h
index de71fcc9d09..f8c2cda0bf9 100644
--- a/src/goto-symex/goto_symex.h
+++ b/src/goto-symex/goto_symex.h
@@ -175,6 +175,10 @@ class goto_symext
   // gotos
   void merge_gotos(statet &state);
 
+  virtual void merge_goto(
+    const statet::goto_statet &goto_state,
+    statet &state);
+
   void merge_value_sets(
     const statet::goto_statet &goto_state,
     statet &dest);
diff --git a/src/goto-symex/goto_symex_state.h b/src/goto-symex/goto_symex_state.h
index 5439af37e05..292dec478c7 100644
--- a/src/goto-symex/goto_symex_state.h
+++ b/src/goto-symex/goto_symex_state.h
@@ -189,6 +189,7 @@ class goto_symex_statet
     level2t::current_namest level2_current_names;
     value_sett value_set;
     guardt guard;
+    symex_targett::sourcet source;
     propagationt propagation;
     unsigned atomic_section_id;
 
@@ -197,6 +198,7 @@ class goto_symex_statet
       level2_current_names(s.level2.current_names),
       value_set(s.value_set),
       guard(s.guard),
+      source(s.source),
       propagation(s.propagation),
       atomic_section_id(s.atomic_section_id)
     {
diff --git a/src/goto-symex/symex_goto.cpp b/src/goto-symex/symex_goto.cpp
index b8e6f1a0a36..8b36cfc26af 100644
--- a/src/goto-symex/symex_goto.cpp
+++ b/src/goto-symex/symex_goto.cpp
@@ -69,6 +69,27 @@ void goto_symext::symex_goto(statet &state)
 
   if(!forward) // backwards?
   {
+    // is it label: goto label; or while(cond); - popular in SV-COMP
+    if(goto_target==state.source.pc ||
+       (instruction.incoming_edges.size()==1 &&
+        *instruction.incoming_edges.begin()==goto_target))
+    {
+      // generate assume(false) or a suitable negation if this
+      // instruction is a conditional goto
+      exprt negated_cond;
+
+      if(new_guard.is_true())
+        negated_cond=false_exprt();
+      else
+        negated_cond=not_exprt(new_guard);
+
+      symex_assume(state, negated_cond);
+
+      // next instruction
+      state.source.pc++;
+      return;
+    }
+
     unsigned &unwind=
       frame.loop_iterations[goto_programt::loop_id(state.source.pc)].count;
     unwind++;
@@ -121,8 +142,6 @@ void goto_symext::symex_goto(statet &state)
     state_pc=goto_target;
   }
 
-  state.source.pc=state_pc;
-
   // put into state-queue
   statet::goto_state_listt &goto_state_list=
     state.top().goto_state_map[new_state_pc];
@@ -130,6 +149,8 @@ void goto_symext::symex_goto(statet &state)
   goto_state_list.push_back(statet::goto_statet(state));
   statet::goto_statet &new_state=goto_state_list.back();
 
+  state.source.pc=state_pc;
+
   // adjust guards
   if(new_guard.is_true())
   {
@@ -244,27 +265,42 @@ void goto_symext::merge_gotos(statet &state)
       list_it=state_list.rbegin();
       list_it!=state_list.rend();
       list_it++)
-  {
-    statet::goto_statet &goto_state=*list_it;
+    merge_goto(*list_it, state);
 
-    // check atomic section
-    if(state.atomic_section_id!=goto_state.atomic_section_id)
-      throw "atomic sections differ across branches";
+  // clean up to save some memory
+  frame.goto_state_map.erase(state_map_it);
+}
 
-    // do SSA phi functions
-    phi_function(goto_state, state);
+/*******************************************************************\
 
-    merge_value_sets(goto_state, state);
+Function: goto_symext::merge_goto
 
-    // adjust guard
-    state.guard|=goto_state.guard;
+  Inputs:
 
-    // adjust depth
-    state.depth=std::min(state.depth, goto_state.depth);
-  }
+ Outputs:
 
-  // clean up to save some memory
-  frame.goto_state_map.erase(state_map_it);
+ Purpose:
+
+\*******************************************************************/
+
+void goto_symext::merge_goto(
+  const statet::goto_statet &goto_state,
+  statet &state)
+{
+  // check atomic section
+  if(state.atomic_section_id!=goto_state.atomic_section_id)
+    throw "atomic sections differ across branches";
+
+  // do SSA phi functions
+  phi_function(goto_state, state);
+
+  merge_value_sets(goto_state, state);
+
+  // adjust guard
+  state.guard|=goto_state.guard;
+
+  // adjust depth
+  state.depth=std::min(state.depth, goto_state.depth);
 }
 
 /*******************************************************************\
diff --git a/src/java_bytecode/Makefile b/src/java_bytecode/Makefile
index 8a672b4e899..8af10aa73e8 100644
--- a/src/java_bytecode/Makefile
+++ b/src/java_bytecode/Makefile
@@ -6,7 +6,7 @@ SRC = java_bytecode_language.cpp java_bytecode_parse_tree.cpp \
       java_root_class.cpp java_bytecode_parser.cpp bytecode_info.cpp \
       java_class_loader.cpp jar_file.cpp java_object_factory.cpp \
       java_bytecode_convert_method.cpp java_local_variable_table.cpp \
-      java_pointer_casts.cpp java_utils.cpp \
+      java_pointer_casts.cpp java_utils.cpp java_class_loader_limit.cpp \
       character_refine_preprocess.cpp \
       # Empty last line
 
diff --git a/src/java_bytecode/bytecode_info.cpp b/src/java_bytecode/bytecode_info.cpp
index 556e208129c..87b1942b54e 100644
--- a/src/java_bytecode/bytecode_info.cpp
+++ b/src/java_bytecode/bytecode_info.cpp
@@ -218,5 +218,5 @@ struct bytecode_infot const bytecode_info[]=
 { "impdep1",        0xfe, ' ', 0, 0, ' ' }, // ; reserved for implementation-dependent operations within debuggers; should not appear in any class file  NOLINT(*)
 { "impdep2",        0xff, ' ', 0, 0, ' ' }, // ; reserved for implementation-dependent operations within debuggers; should not appear in any class file  NOLINT(*)
 { "wide",           0xc4, ' ', 0, 0, ' ' }, // modifier for others  NOLINT(*)
-{ 0, 0 }
+{ nullptr,          0x00, '\0',0, 0, '\0'}, // zero-initialized NOLINT (*)
 };
diff --git a/src/java_bytecode/jar_file.cpp b/src/java_bytecode/jar_file.cpp
index 07d7719e500..ee08a50838a 100644
--- a/src/java_bytecode/jar_file.cpp
+++ b/src/java_bytecode/jar_file.cpp
@@ -12,7 +12,9 @@ Author: Daniel Kroening, kroening@kroening.com
 
 #include 
 #include 
+
 #include "jar_file.h"
+
 /*******************************************************************\
 
 Function: jar_filet::open
@@ -26,7 +28,7 @@ Function: jar_filet::open
 \*******************************************************************/
 
 void jar_filet::open(
-  std::string &java_cp_include_files,
+  java_class_loader_limitt &class_loader_limit,
   const std::string &filename)
 {
   if(!mz_ok)
@@ -38,34 +40,6 @@ void jar_filet::open(
 
   if(mz_ok)
   {
-    // '@' signals file reading with list of class files to load
-    bool regex_match=java_cp_include_files[0]!='@';
-    std::regex regex_matcher;
-    std::smatch string_matcher;
-    std::unordered_set set_matcher;
-    jsont json_cp_config;
-    if(regex_match)
-      regex_matcher=std::regex(java_cp_include_files);
-    else
-    {
-      assert(java_cp_include_files.length()>1);
-      if(parse_json(
-           java_cp_include_files.substr(1),
-           get_message_handler(),
-           json_cp_config))
-        throw "cannot read JSON input configuration for JAR loading";
-      if(!json_cp_config.is_object())
-        throw "the JSON file has a wrong format";
-      jsont include_files=json_cp_config["classFiles"];
-      if(!include_files.is_array())
-        throw "the JSON file has a wrong format";
-      for(const jsont &file_entry : include_files.array)
-      {
-        assert(file_entry.is_string());
-        set_matcher.insert(file_entry.value);
-      }
-    }
-
     std::size_t number_of_files=
       mz_zip_reader_get_num_files(&zip);
 
@@ -80,12 +54,8 @@ void jar_filet::open(
 
       // non-class files are loaded in any case
       bool add_file=!has_suffix(file_name, ".class");
-      // load .class file only if they match regex
-      if(regex_match)
-        add_file|=std::regex_match(file_name, string_matcher, regex_matcher);
-      // load .class file only if it is in the match set
-      else
-        add_file|=set_matcher.find(file_name)!=set_matcher.end();
+      // load .class file only if they match regex / are in match set
+      add_file|=class_loader_limit.load_class_file(file_name);
       if(add_file)
       {
         if(has_suffix(file_name, ".class"))
diff --git a/src/java_bytecode/jar_file.h b/src/java_bytecode/jar_file.h
index 9407e711128..3ecdfc80d0f 100644
--- a/src/java_bytecode/jar_file.h
+++ b/src/java_bytecode/jar_file.h
@@ -18,6 +18,8 @@ Author: Daniel Kroening, kroening@kroening.com
 #include 
 #include 
 
+#include "java_class_loader_limit.h"
+
 class jar_filet:public messaget
 {
 public:
@@ -25,7 +27,7 @@ class jar_filet:public messaget
 
   ~jar_filet();
 
-  void open(std::string &java_cp_include_files, const std::string &);
+  void open(java_class_loader_limitt &, const std::string &);
 
   // Test for error; 'true' means we are good.
   explicit operator bool() const { return mz_ok; }
@@ -47,21 +49,16 @@ class jar_filet:public messaget
 class jar_poolt:public messaget
 {
 public:
-  void set_java_cp_include_files(std::string &_java_cp_include_files)
-  {
-    java_cp_include_files=_java_cp_include_files;
-  }
-
-  jar_filet &operator()(const std::string &file_name)
+  jar_filet &operator()(
+    java_class_loader_limitt &class_loader_limit,
+    const std::string &file_name)
   {
-    if(java_cp_include_files.empty())
-      throw "class regexp cannot be empty";
     file_mapt::iterator it=file_map.find(file_name);
     if(it==file_map.end())
     {
       jar_filet &jar_file=file_map[file_name];
       jar_file.set_message_handler(get_message_handler());
-      jar_file.open(java_cp_include_files, file_name);
+      jar_file.open(class_loader_limit, file_name);
       return jar_file;
     }
     else
diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp
index 7f52c6ef77b..27bc41ba151 100644
--- a/src/java_bytecode/java_bytecode_convert_class.cpp
+++ b/src/java_bytecode/java_bytecode_convert_class.cpp
@@ -27,14 +27,12 @@ class java_bytecode_convert_classt:public messaget
   java_bytecode_convert_classt(
     symbol_tablet &_symbol_table,
     message_handlert &_message_handler,
-    bool _disable_runtime_checks,
     size_t _max_array_length,
     lazy_methodst& _lazy_methods,
     lazy_methods_modet _lazy_methods_mode,
     bool _string_refinement_enabled):
     messaget(_message_handler),
     symbol_table(_symbol_table),
-    disable_runtime_checks(_disable_runtime_checks),
     max_array_length(_max_array_length),
     lazy_methods(_lazy_methods),
     lazy_methods_mode(_lazy_methods_mode),
@@ -69,7 +67,6 @@ class java_bytecode_convert_classt:public messaget
 
 protected:
   symbol_tablet &symbol_table;
-  const bool disable_runtime_checks;
   const size_t max_array_length;
   lazy_methodst &lazy_methods;
   lazy_methods_modet lazy_methods_mode;
@@ -178,7 +175,6 @@ void java_bytecode_convert_classt::convert(const classt &c)
         method,
         symbol_table,
         get_message_handler(),
-        disable_runtime_checks,
         max_array_length);
     }
     else
@@ -373,7 +369,6 @@ bool java_bytecode_convert_class(
   const java_bytecode_parse_treet &parse_tree,
   symbol_tablet &symbol_table,
   message_handlert &message_handler,
-  bool disable_runtime_checks,
   size_t max_array_length,
   lazy_methodst &lazy_methods,
   lazy_methods_modet lazy_methods_mode,
@@ -382,7 +377,6 @@ bool java_bytecode_convert_class(
   java_bytecode_convert_classt java_bytecode_convert_class(
     symbol_table,
     message_handler,
-    disable_runtime_checks,
     max_array_length,
     lazy_methods,
     lazy_methods_mode,
diff --git a/src/java_bytecode/java_bytecode_convert_class.h b/src/java_bytecode/java_bytecode_convert_class.h
index 0d2be3d8202..9ce5cc8c7cc 100644
--- a/src/java_bytecode/java_bytecode_convert_class.h
+++ b/src/java_bytecode/java_bytecode_convert_class.h
@@ -19,7 +19,6 @@ bool java_bytecode_convert_class(
   const java_bytecode_parse_treet &parse_tree,
   symbol_tablet &symbol_table,
   message_handlert &message_handler,
-  bool disable_runtime_checks,
   size_t max_array_length,
   lazy_methodst &,
   lazy_methods_modet,
diff --git a/src/java_bytecode/java_bytecode_convert_method.cpp b/src/java_bytecode/java_bytecode_convert_method.cpp
index 8e14d5731dc..4888810bd83 100644
--- a/src/java_bytecode/java_bytecode_convert_method.cpp
+++ b/src/java_bytecode/java_bytecode_convert_method.cpp
@@ -1171,20 +1171,17 @@ codet java_bytecode_convert_methodt::convert_instructions(
     {
       assert(op.size()==1 && results.size()==1);
       code_blockt block;
-      if(!disable_runtime_checks)
-      {
-        // TODO throw NullPointerException instead
-        const typecast_exprt lhs(op[0], pointer_typet(empty_typet()));
-        const exprt rhs(null_pointer_exprt(to_pointer_type(lhs.type())));
-        const exprt not_equal_null(
-          binary_relation_exprt(lhs, ID_notequal, rhs));
-        code_assertt check(not_equal_null);
-        check.add_source_location()
-          .set_comment("Throw null");
-        check.add_source_location()
-          .set_property_class("null-pointer-exception");
-        block.move_to_operands(check);
-      }
+      // TODO throw NullPointerException instead
+      const typecast_exprt lhs(op[0], pointer_typet(empty_typet()));
+      const exprt rhs(null_pointer_exprt(to_pointer_type(lhs.type())));
+      const exprt not_equal_null(
+        binary_relation_exprt(lhs, ID_notequal, rhs));
+      code_assertt check(not_equal_null);
+      check.add_source_location()
+        .set_comment("Throw null");
+      check.add_source_location()
+        .set_property_class("null-pointer-exception");
+      block.move_to_operands(check);
 
       side_effect_expr_throwt throw_expr;
       throw_expr.add_source_location()=i_it->source_location;
@@ -1197,20 +1194,15 @@ codet java_bytecode_convert_methodt::convert_instructions(
     }
     else if(statement=="checkcast")
     {
-      if(!disable_runtime_checks)
-      {
-        // checkcast throws an exception in case a cast of object
-        // on stack to given type fails.
-        // The stack isn't modified.
-        // TODO: convert assertions to exceptions.
-        assert(op.size()==1 && results.size()==1);
-        binary_predicate_exprt check(op[0], ID_java_instanceof, arg0);
-        c=code_assertt(check);
-        c.add_source_location().set_comment("Dynamic cast check");
-        c.add_source_location().set_property_class("bad-dynamic-cast");
-      }
-      else
-        c=code_skipt();
+      // checkcast throws an exception in case a cast of object
+      // on stack to given type fails.
+      // The stack isn't modified.
+      // TODO: convert assertions to exceptions.
+      assert(op.size()==1 && results.size()==1);
+      binary_predicate_exprt check(op[0], ID_java_instanceof, arg0);
+      c=code_assertt(check);
+      c.add_source_location().set_comment("Dynamic cast check");
+      c.add_source_location().set_property_class("bad-dynamic-cast");
 
       results[0]=op[0];
     }
@@ -1423,13 +1415,10 @@ codet java_bytecode_convert_methodt::convert_instructions(
       const dereference_exprt element(data_plus_offset, element_type);
 
       c=code_blockt();
-      if(!disable_runtime_checks)
-      {
-        codet bounds_check=
-          get_array_bounds_check(deref, op[1], i_it->source_location);
-        bounds_check.add_source_location()=i_it->source_location;
-        c.move_to_operands(bounds_check);
-      }
+      codet bounds_check=
+        get_array_bounds_check(deref, op[1], i_it->source_location);
+      bounds_check.add_source_location()=i_it->source_location;
+      c.move_to_operands(bounds_check);
       code_assignt array_put(element, op[2]);
       array_put.add_source_location()=i_it->source_location;
       c.move_to_operands(array_put);
@@ -1469,11 +1458,8 @@ codet java_bytecode_convert_methodt::convert_instructions(
       typet element_type=data_ptr.type().subtype();
       dereference_exprt element(data_plus_offset, element_type);
 
-      if(!disable_runtime_checks)
-      {
-        c=get_array_bounds_check(deref, op[1], i_it->source_location);
-        c.add_source_location()=i_it->source_location;
-      }
+      c=get_array_bounds_check(deref, op[1], i_it->source_location);
+      c.add_source_location()=i_it->source_location;
       results[0]=java_bytecode_promotion(element);
     }
     else if(statement==patternt("?load"))
@@ -2014,17 +2000,15 @@ codet java_bytecode_convert_methodt::convert_instructions(
         java_new_array.add_source_location()=i_it->source_location;
 
       c=code_blockt();
-      if(!disable_runtime_checks)
-      {
-        // TODO make this throw NegativeArrayIndexException instead.
-        constant_exprt intzero=from_integer(0, java_int_type());
-        binary_relation_exprt gezero(op[0], ID_ge, intzero);
-        code_assertt check(gezero);
-        check.add_source_location().set_comment("Array size < 0");
-        check.add_source_location()
-          .set_property_class("array-create-negative-size");
-        c.move_to_operands(check);
-      }
+      // TODO make this throw NegativeArrayIndexException instead.
+      constant_exprt intzero=from_integer(0, java_int_type());
+      binary_relation_exprt gezero(op[0], ID_ge, intzero);
+      code_assertt check(gezero);
+      check.add_source_location().set_comment("Array size < 0");
+      check.add_source_location()
+        .set_property_class("array-create-negative-size");
+      c.move_to_operands(check);
+
       if(max_array_length!=0)
       {
         constant_exprt size_limit=
@@ -2056,26 +2040,24 @@ codet java_bytecode_convert_methodt::convert_instructions(
         java_new_array.add_source_location()=i_it->source_location;
 
       code_blockt checkandcreate;
-      if(!disable_runtime_checks)
+      // TODO make this throw NegativeArrayIndexException instead.
+      constant_exprt intzero=from_integer(0, java_int_type());
+      binary_relation_exprt gezero(op[0], ID_ge, intzero);
+      code_assertt check(gezero);
+      check.add_source_location().set_comment("Array size < 0");
+      check.add_source_location()
+        .set_property_class("array-create-negative-size");
+      checkandcreate.move_to_operands(check);
+
+      if(max_array_length!=0)
       {
-        // TODO make this throw NegativeArrayIndexException instead.
-        constant_exprt intzero=from_integer(0, java_int_type());
-        binary_relation_exprt gezero(op[0], ID_ge, intzero);
-        code_assertt check(gezero);
-        check.add_source_location().set_comment("Array size < 0");
-        check.add_source_location()
-          .set_property_class("array-create-negative-size");
-        checkandcreate.move_to_operands(check);
-
-        if(max_array_length!=0)
-        {
-          constant_exprt size_limit=
-            from_integer(max_array_length, java_int_type());
-          binary_relation_exprt le_max_size(op[0], ID_le, size_limit);
-          code_assumet assume_le_max_size(le_max_size);
-          checkandcreate.move_to_operands(assume_le_max_size);
-        }
+        constant_exprt size_limit=
+          from_integer(max_array_length, java_int_type());
+        binary_relation_exprt le_max_size(op[0], ID_le, size_limit);
+        code_assumet assume_le_max_size(le_max_size);
+        checkandcreate.move_to_operands(assume_le_max_size);
       }
+
       const exprt tmp=tmp_variable("newarray", ref_type);
       c=code_assignt(tmp, java_new_array);
       results[0]=tmp;
@@ -2416,7 +2398,8 @@ codet java_bytecode_convert_methodt::convert_instructions(
   // First create a simple flat list of basic blocks. We'll add lexical nesting
   // constructs as variable live-ranges require next.
   bool start_new_block=true;
-  int previous_address=-1;
+  bool has_seen_previous_address=false;
+  unsigned previous_address=0;
   for(const auto &address_pair : address_map)
   {
     const unsigned address=address_pair.first;
@@ -2431,7 +2414,7 @@ codet java_bytecode_convert_methodt::convert_instructions(
     if(!start_new_block)
       start_new_block=address_pair.second.predecessors.size()>1;
     // Start a new lexical block if we've just entered a try block
-    if(!start_new_block && previous_address!=-1)
+    if(!start_new_block && has_seen_previous_address)
     {
       for(const auto &exception_row : method.exception_table)
         if(exception_row.start_pc==previous_address)
@@ -2461,6 +2444,7 @@ codet java_bytecode_convert_methodt::convert_instructions(
     start_new_block=address_pair.second.successors.size()>1;
 
     previous_address=address;
+    has_seen_previous_address=true;
   }
 
   // Find out where temporaries are used:
@@ -2543,7 +2527,6 @@ void java_bytecode_convert_method(
   const java_bytecode_parse_treet::methodt &method,
   symbol_tablet &symbol_table,
   message_handlert &message_handler,
-  bool disable_runtime_checks,
   size_t max_array_length,
   safe_pointer > needed_methods,
   safe_pointer > needed_classes)
@@ -2551,7 +2534,6 @@ void java_bytecode_convert_method(
   java_bytecode_convert_methodt java_bytecode_convert_method(
     symbol_table,
     message_handler,
-    disable_runtime_checks,
     max_array_length,
     needed_methods,
     needed_classes);
diff --git a/src/java_bytecode/java_bytecode_convert_method.h b/src/java_bytecode/java_bytecode_convert_method.h
index e81881f44e1..bc25eccb0c7 100644
--- a/src/java_bytecode/java_bytecode_convert_method.h
+++ b/src/java_bytecode/java_bytecode_convert_method.h
@@ -22,7 +22,6 @@ void java_bytecode_convert_method(
   const java_bytecode_parse_treet::methodt &,
   symbol_tablet &symbol_table,
   message_handlert &message_handler,
-  bool disable_runtime_checks,
   size_t max_array_length,
   safe_pointer > needed_methods,
   safe_pointer > needed_classes);
@@ -33,7 +32,6 @@ inline void java_bytecode_convert_method(
   const java_bytecode_parse_treet::methodt &method,
   symbol_tablet &symbol_table,
   message_handlert &message_handler,
-  bool disable_runtime_checks,
   size_t max_array_length)
 {
   java_bytecode_convert_method(
@@ -41,7 +39,6 @@ inline void java_bytecode_convert_method(
     method,
     symbol_table,
     message_handler,
-    disable_runtime_checks,
     max_array_length,
     safe_pointer >::create_null(),
     safe_pointer >::create_null());
diff --git a/src/java_bytecode/java_bytecode_convert_method_class.h b/src/java_bytecode/java_bytecode_convert_method_class.h
index 263d0c68810..d260b82bbc8 100644
--- a/src/java_bytecode/java_bytecode_convert_method_class.h
+++ b/src/java_bytecode/java_bytecode_convert_method_class.h
@@ -30,13 +30,11 @@ class java_bytecode_convert_methodt:public messaget
   java_bytecode_convert_methodt(
     symbol_tablet &_symbol_table,
     message_handlert &_message_handler,
-    bool _disable_runtime_checks,
     size_t _max_array_length,
     safe_pointer > _needed_methods,
     safe_pointer > _needed_classes):
     messaget(_message_handler),
     symbol_table(_symbol_table),
-    disable_runtime_checks(_disable_runtime_checks),
     max_array_length(_max_array_length),
     needed_methods(_needed_methods),
     needed_classes(_needed_classes)
@@ -56,7 +54,6 @@ class java_bytecode_convert_methodt:public messaget
 
 protected:
   symbol_tablet &symbol_table;
-  const bool disable_runtime_checks;
   const size_t max_array_length;
   safe_pointer > needed_methods;
   safe_pointer > needed_classes;
diff --git a/src/java_bytecode/java_bytecode_language.cpp b/src/java_bytecode/java_bytecode_language.cpp
index 8ab88cf9dc6..43e6fac96c0 100644
--- a/src/java_bytecode/java_bytecode_language.cpp
+++ b/src/java_bytecode/java_bytecode_language.cpp
@@ -42,7 +42,6 @@ Function: java_bytecode_languaget::get_language_options
 
 void java_bytecode_languaget::get_language_options(const cmdlinet &cmd)
 {
-  disable_runtime_checks=cmd.isset("disable-runtime-check");
   assume_inputs_non_null=cmd.isset("java-assume-inputs-non-null");
   string_refinement_enabled=cmd.isset("refine-strings");
   if(cmd.isset("java-max-input-array-length"))
@@ -170,11 +169,14 @@ bool java_bytecode_languaget::parse(
   }
   else if(has_suffix(path, ".jar"))
   {
+    java_class_loader_limitt class_loader_limit(
+      get_message_handler(),
+      java_cp_include_files);
     if(config.java.main_class.empty())
     {
       // Does it have a main class set in the manifest?
       jar_filet::manifestt manifest=
-        java_class_loader.jar_pool(path).get_manifest();
+        java_class_loader.jar_pool(class_loader_limit, path).get_manifest();
       std::string manifest_main_class=manifest["Main-Class"];
 
       if(manifest_main_class!="")
@@ -186,8 +188,8 @@ bool java_bytecode_languaget::parse(
     // Do we have one now?
     if(main_class.empty())
     {
-      status() << "JAR file without entry point: loading it all" << eom;
-      java_class_loader.load_entire_jar(path);
+      status() << "JAR file without entry point: loading class files" << eom;
+      java_class_loader.load_entire_jar(class_loader_limit, path);
       for(const auto &kv : java_class_loader.jar_map.at(path).entries)
         main_jar_classes.push_back(kv.first);
     }
@@ -387,9 +389,16 @@ static void gather_needed_globals(
 {
   if(e.id()==ID_symbol)
   {
-    const auto &sym=symbol_table.lookup(to_symbol_expr(e).get_identifier());
-    if(sym.is_static_lifetime)
-      needed.add(sym);
+    // If the symbol isn't in the symbol table at all, then it is defined
+    // on an opaque type (i.e. we don't have the class definition at this point)
+    // and will be created during the typecheck phase.
+    // We don't mark it as 'needed' as it doesn't exist yet to keep.
+    auto findit=symbol_table.symbols.find(to_symbol_expr(e).get_identifier());
+    if(findit!=symbol_table.symbols.end() &&
+       findit->second.is_static_lifetime)
+    {
+      needed.add(findit->second);
+    }
   }
   else
     forall_operands(opit, e)
@@ -518,7 +527,6 @@ bool java_bytecode_languaget::typecheck(
          c_it->second,
          symbol_table,
          get_message_handler(),
-         disable_runtime_checks,
          max_user_array_length,
          lazy_methods,
          lazy_methods_mode,
@@ -639,7 +647,6 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion(
           *parsed_method.second,
           symbol_table,
           get_message_handler(),
-          disable_runtime_checks,
           max_user_array_length,
           safe_pointer >::create_non_null(
             &method_worklist2),
@@ -754,7 +761,6 @@ void java_bytecode_languaget::convert_lazy_method(
     *lazy_method_entry.second,
     symtab,
     get_message_handler(),
-    disable_runtime_checks,
     max_user_array_length);
 }
 
diff --git a/src/java_bytecode/java_bytecode_language.h b/src/java_bytecode/java_bytecode_language.h
index b3bdc8a5aa1..2da26b71ad6 100644
--- a/src/java_bytecode/java_bytecode_language.h
+++ b/src/java_bytecode/java_bytecode_language.h
@@ -94,12 +94,6 @@ class java_bytecode_languaget:public languaget
   std::vector main_jar_classes;
   java_class_loadert java_class_loader;
   bool assume_inputs_non_null;      // assume inputs variables to be non-null
-
-  bool disable_runtime_checks;      // disable run-time checks for java, i.e.,
-                                    // ASSERTS for
-                                    //  - checkcast / instanceof
-                                    //  - array bounds check
-                                    //  - array size for newarray
   size_t max_nondet_array_length;   // maximal length for non-det array creation
   size_t max_user_array_length;     // max size for user code created arrays
   lazy_methodst lazy_methods;
diff --git a/src/java_bytecode/java_class_loader.cpp b/src/java_bytecode/java_class_loader.cpp
index db5f63b08b9..fdd37c4b312 100644
--- a/src/java_bytecode/java_class_loader.cpp
+++ b/src/java_bytecode/java_class_loader.cpp
@@ -44,6 +44,9 @@ java_bytecode_parse_treet &java_class_loadert::operator()(
   queue.push("java.lang.Class");
   queue.push(class_name);
 
+  java_class_loader_limitt class_loader_limit(
+    get_message_handler(), java_cp_include_files);
+
   while(!queue.empty())
   {
     irep_idt c=queue.top();
@@ -56,7 +59,7 @@ java_bytecode_parse_treet &java_class_loadert::operator()(
     debug() << "Reading class " << c << eom;
 
     java_bytecode_parse_treet &parse_tree=
-      get_parse_tree(c);
+      get_parse_tree(class_loader_limit, c);
 
     // add any dependencies to queue
     for(java_bytecode_parse_treet::class_refst::const_iterator
@@ -71,6 +74,25 @@ java_bytecode_parse_treet &java_class_loadert::operator()(
 
 /*******************************************************************\
 
+Function: java_class_loadert::set_java_cp_include_files
+
+  Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+void java_class_loadert::set_java_cp_include_files(
+  std::string &_java_cp_include_files)
+{
+  java_cp_include_files=_java_cp_include_files;
+  jar_pool.set_message_handler(get_message_handler());
+}
+
+/*******************************************************************\
+
 Function: java_class_loadert::get_parse_tree
 
   Inputs:
@@ -82,6 +104,7 @@ Function: java_class_loadert::get_parse_tree
 \*******************************************************************/
 
 java_bytecode_parse_treet &java_class_loadert::get_parse_tree(
+  java_class_loader_limitt &class_loader_limit,
   const irep_idt &class_name)
 {
   java_bytecode_parse_treet &parse_tree=class_map[class_name];
@@ -89,7 +112,7 @@ java_bytecode_parse_treet &java_class_loadert::get_parse_tree(
   // First check given JAR files
   for(const auto &jf : jar_files)
   {
-    read_jar_file(jf);
+    read_jar_file(class_loader_limit, jf);
 
     const auto &jm=jar_map[jf];
 
@@ -100,7 +123,8 @@ java_bytecode_parse_treet &java_class_loadert::get_parse_tree(
       debug() << "Getting class `" << class_name << "' from JAR "
               << jf << eom;
 
-      std::string data=jar_pool(jf).get_entry(jm_it->second.class_file_name);
+      std::string data=jar_pool(class_loader_limit, jf)
+        .get_entry(jm_it->second.class_file_name);
 
       std::istringstream istream(data);
 
@@ -114,13 +138,12 @@ java_bytecode_parse_treet &java_class_loadert::get_parse_tree(
   }
 
   // See if we can find it in the class path
-
   for(const auto &cp : config.java.classpath)
   {
     // in a JAR?
     if(has_suffix(cp, ".jar"))
     {
-      read_jar_file(cp);
+      read_jar_file(class_loader_limit, cp);
 
       const auto &jm=jar_map[cp];
 
@@ -131,7 +154,8 @@ java_bytecode_parse_treet &java_class_loadert::get_parse_tree(
         debug() << "Getting class `" << class_name << "' from JAR "
                 << cp << eom;
 
-        std::string data=jar_pool(cp).get_entry(jm_it->second.class_file_name);
+        std::string data=jar_pool(class_loader_limit, cp)
+          .get_entry(jm_it->second.class_file_name);
 
         std::istringstream istream(data);
 
@@ -153,7 +177,9 @@ java_bytecode_parse_treet &java_class_loadert::get_parse_tree(
         cp+'/'+class_name_to_file(class_name);
         #endif
 
-      if(std::ifstream(full_path))
+      // full class path starts with './'
+      if(class_loader_limit.load_class_file(full_path.substr(2)) &&
+         std::ifstream(full_path))
       {
         if(!java_bytecode_parse(
              full_path,
@@ -182,9 +208,11 @@ Function: java_class_loadert::load_entire_jar
 
 \*******************************************************************/
 
-void java_class_loadert::load_entire_jar(const std::string &file)
+void java_class_loadert::load_entire_jar(
+  java_class_loader_limitt &class_loader_limit,
+  const std::string &file)
 {
-  read_jar_file(file);
+  read_jar_file(class_loader_limit, file);
 
   const auto &jm=jar_map[file];
 
@@ -208,13 +236,15 @@ Function: java_class_loadert::read_jar_file
 
 \*******************************************************************/
 
-void java_class_loadert::read_jar_file(const irep_idt &file)
+void java_class_loadert::read_jar_file(
+  java_class_loader_limitt &class_loader_limit,
+  const irep_idt &file)
 {
   // done already?
   if(jar_map.find(file)!=jar_map.end())
     return;
 
-  jar_filet &jar_file=jar_pool(id2string(file));
+  jar_filet &jar_file=jar_pool(class_loader_limit, id2string(file));
 
   if(!jar_file)
   {
diff --git a/src/java_bytecode/java_class_loader.h b/src/java_bytecode/java_class_loader.h
index 7a8f6da2b5c..c4676ff31f0 100644
--- a/src/java_bytecode/java_class_loader.h
+++ b/src/java_bytecode/java_class_loader.h
@@ -10,10 +10,13 @@ Author: Daniel Kroening, kroening@kroening.com
 #define CPROVER_JAVA_BYTECODE_JAVA_CLASS_LOADER_H
 
 #include 
+#include 
+#include 
 
 #include 
 
 #include "java_bytecode_parse_tree.h"
+#include "java_class_loader_limit.h"
 #include "jar_file.h"
 
 class java_class_loadert:public messaget
@@ -21,11 +24,7 @@ class java_class_loadert:public messaget
 public:
   java_bytecode_parse_treet &operator()(const irep_idt &);
 
-  void set_java_cp_include_files(std::string &java_cp_include_files)
-  {
-    jar_pool.set_java_cp_include_files(java_cp_include_files);
-    jar_pool.set_message_handler(get_message_handler());
-  }
+  void set_java_cp_include_files(std::string &);
 
   // maps class names to the parse trees
   typedef std::map class_mapt;
@@ -39,7 +38,7 @@ class java_class_loadert:public messaget
     jar_files.push_back(f);
   }
 
-  void load_entire_jar(const std::string &f);
+  void load_entire_jar(java_class_loader_limitt &, const std::string &f);
 
   jar_poolt jar_pool;
 
@@ -60,12 +59,14 @@ class java_class_loadert:public messaget
   typedef std::map jar_mapt;
   jar_mapt jar_map;
 
-  void read_jar_file(const irep_idt &);
+  void read_jar_file(java_class_loader_limitt &, const irep_idt &);
 
   // get a parse tree for given class
-  java_bytecode_parse_treet &get_parse_tree(const irep_idt &);
+  java_bytecode_parse_treet &get_parse_tree(
+    java_class_loader_limitt &, const irep_idt &);
 
   std::list jar_files;
+  std::string java_cp_include_files;
 };
 
 #endif // CPROVER_JAVA_BYTECODE_JAVA_CLASS_LOADER_H
diff --git a/src/java_bytecode/java_class_loader_limit.cpp b/src/java_bytecode/java_class_loader_limit.cpp
new file mode 100644
index 00000000000..3a9ed66d3d5
--- /dev/null
+++ b/src/java_bytecode/java_class_loader_limit.cpp
@@ -0,0 +1,81 @@
+/*******************************************************************\
+
+Module: limit class path loading
+
+Author: Daniel Kroening, kroening@kroening.com
+
+\*******************************************************************/
+
+#include 
+
+#include "java_class_loader_limit.h"
+
+/*******************************************************************\
+
+Function: java_class_loader_limitt::setup_class_load_limit
+
+  Inputs: parameter from `java-cp-include-files`
+
+ Outputs:
+
+ Purpose: initializes class with either regex matcher or match set
+
+\*******************************************************************/
+
+void java_class_loader_limitt::setup_class_load_limit(
+  std::string &java_cp_include_files)
+{
+  if(java_cp_include_files.empty())
+    throw "class regexp cannot be empty";
+
+  // '@' signals file reading with list of class files to load
+  regex_match=java_cp_include_files[0]!='@';
+  if(regex_match)
+    regex_matcher=std::regex(java_cp_include_files);
+  else
+  {
+    assert(java_cp_include_files.length()>1);
+    jsont json_cp_config;
+    if(parse_json(
+         java_cp_include_files.substr(1),
+         get_message_handler(),
+         json_cp_config))
+      throw "cannot read JSON input configuration for JAR loading";
+    if(!json_cp_config.is_object())
+      throw "the JSON file has a wrong format";
+    jsont include_files=json_cp_config["classFiles"];
+    if(!include_files.is_null() && !include_files.is_array())
+      throw "the JSON file has a wrong format";
+    for(const jsont &file_entry : include_files.array)
+    {
+      assert(file_entry.is_string());
+      set_matcher.insert(file_entry.value);
+    }
+  }
+}
+
+/*******************************************************************\
+
+Function: java_class_loader_limitt::load_class_file
+
+  Inputs: class file name
+
+ Outputs: true if file should be loaded, else false
+
+ Purpose:
+
+\*******************************************************************/
+
+bool java_class_loader_limitt::load_class_file(const irep_idt &file_name)
+{
+  if(regex_match)
+  {
+    return std::regex_match(
+      id2string(file_name),
+      string_matcher,
+      regex_matcher);
+  }
+  // load .class file only if it is in the match set
+  else
+    return set_matcher.find(id2string(file_name))!=set_matcher.end();
+}
diff --git a/src/java_bytecode/java_class_loader_limit.h b/src/java_bytecode/java_class_loader_limit.h
new file mode 100644
index 00000000000..fa5e21ffd95
--- /dev/null
+++ b/src/java_bytecode/java_class_loader_limit.h
@@ -0,0 +1,38 @@
+/*******************************************************************\
+
+Module: limit class path loading
+
+Author: Daniel Kroening, kroening@kroening.com
+
+\*******************************************************************/
+
+#ifndef CPROVER_JAVA_BYTECODE_JAVA_CLASS_LOADER_LIMIT_H
+#define CPROVER_JAVA_BYTECODE_JAVA_CLASS_LOADER_LIMIT_H
+
+#include 
+#include 
+
+#include 
+#include 
+
+class java_class_loader_limitt:public messaget
+{
+  std::regex regex_matcher;
+  std::set set_matcher;
+  bool regex_match;
+  std::smatch string_matcher;
+
+  void setup_class_load_limit(std::string &);
+ public:
+  explicit java_class_loader_limitt(
+    message_handlert &_message_handler,
+    std::string &java_cp_include_files) :
+  messaget(_message_handler),
+    regex_match(false)
+  {
+    setup_class_load_limit(java_cp_include_files);
+  }
+  bool load_class_file(const irep_idt &class_file_name);
+};
+
+#endif
diff --git a/src/java_bytecode/java_local_variable_table.cpp b/src/java_bytecode/java_local_variable_table.cpp
index 33e8a39f5db..85e9766d5ab 100644
--- a/src/java_bytecode/java_local_variable_table.cpp
+++ b/src/java_bytecode/java_local_variable_table.cpp
@@ -352,7 +352,7 @@ static void populate_predecessor_map(
             // handling is presently vague (any subroutine is assumed to
             // be able to return to any callsite)
             msg.warning() << "Local variable table: ignoring flow from "
-                          << "out of range for " << it->var.name << " "
+                          << "out of range for " << it->var.name << ' '
                           << pred << " -> " << amapit->first
                           << messaget::eom;
             continue;
@@ -375,7 +375,7 @@ static void populate_predecessor_map(
             // assumed to be able to return to any callsite)
             msg.warning() << "Local variable table: ignoring flow from "
                           << "clashing variable for "
-                          << it->var.name << " " << pred << " -> "
+                          << it->var.name << ' ' << pred << " -> "
                           << amapit->first << messaget::eom;
             continue;
           }
@@ -549,9 +549,8 @@ static void merge_variable_table_entries(
 #ifdef DEBUG
   debug_out << "Merged " << merge_vars.size() << " variables named "
             << merge_into.var.name << "; new live range "
-            << merge_into.var.start_pc << "-"
-            << merge_into.var.start_pc + merge_into.var.length
-            << messaget::eom;
+            << merge_into.var.start_pc << '-'
+            << merge_into.var.start_pc + merge_into.var.length << '\n';
 #endif
 
   // Nuke the now-subsumed var-table entries:
diff --git a/src/jsil/jsil_typecheck.cpp b/src/jsil/jsil_typecheck.cpp
index 38a1b94e6be..a644f1acf99 100644
--- a/src/jsil/jsil_typecheck.cpp
+++ b/src/jsil/jsil_typecheck.cpp
@@ -87,7 +87,10 @@ void jsil_typecheckt::update_expr_type(exprt &expr, const typet &type)
     const irep_idt &id=to_symbol_expr(expr).get_identifier();
 
     if(!symbol_table.has_symbol(id))
-      throw "unexpected symbol: "+id2string(id);
+    {
+      error() << "unexpected symbol: " << id << eom;
+      throw 0;
+    }
 
     symbolt &s=symbol_table.lookup(id);
     if(s.type.id().empty() || s.type.is_nil())
@@ -924,7 +927,10 @@ void jsil_typecheckt::typecheck_symbol_expr(symbol_exprt &symbol_expr)
       symbol_table.symbols.find(identifier);
 
     if(s_it==symbol_table.symbols.end())
-      throw "unexpected internal symbol: "+id2string(identifier);
+    {
+      error() << "unexpected internal symbol: " << identifier << eom;
+      throw 0;
+    }
     else
     {
       // symbol already exists
@@ -1006,7 +1012,12 @@ void jsil_typecheckt::typecheck_code(codet &code)
   else if(statement==ID_expression)
   {
     if(code.operands().size()!=1)
-      throw "expression statement expected to have one operand";
+    {
+      err_location(code);
+      error() << "expression statement expected to have one operand"
+              << eom;
+      throw 0;
+    }
 
     typecheck_expr(code.op0());
   }
@@ -1090,7 +1101,11 @@ void jsil_typecheckt::typecheck_try_catch(code_try_catcht &code)
 {
   // A special case of try catch with one catch clause
   if(code.operands().size()!=3)
-    throw "try_catch expected to have three operands";
+  {
+    err_location(code);
+    error() << "try_catch expected to have three operands" << eom;
+    throw 0;
+  }
 
   // function call
   typecheck_function_call(to_code_function_call(code.try_code()));
@@ -1116,7 +1131,11 @@ void jsil_typecheckt::typecheck_function_call(
   code_function_callt &call)
 {
   if(call.operands().size()!=3)
-    throw "function call expected to have three operands";
+  {
+    err_location(call);
+    error() << "function call expected to have three operands" << eom;
+    throw 0;
+  }
 
   exprt &lhs=call.lhs();
   typecheck_expr(lhs);
@@ -1194,7 +1213,12 @@ void jsil_typecheckt::typecheck_function_call(
       make_type_compatible(lhs, jsil_any_type(), true);
 
       if(symbol_table.add(new_symbol))
-        throw "failed to add expression symbol to symbol table";
+      {
+        error().source_location=new_symbol.location;
+        error() << "failed to add expression symbol to symbol table"
+                << eom;
+        throw 0;
+      }
     }
   }
   else
@@ -1287,8 +1311,12 @@ void jsil_typecheckt::typecheck_non_type_symbol(symbolt &symbol)
     // Do nothing
   }
   else
-    throw "non-type symbol value expected code, but got "+
-      symbol.value.pretty();
+  {
+    error().source_location=symbol.location;
+    error() << "non-type symbol value expected code, but got "
+            << symbol.value.pretty() << eom;
+    throw 0;
+  }
 }
 
 /*******************************************************************\
diff --git a/src/langapi/language_ui.cpp b/src/langapi/language_ui.cpp
index 4b0f3fa0d75..f516f57622d 100644
--- a/src/langapi/language_ui.cpp
+++ b/src/langapi/language_ui.cpp
@@ -31,10 +31,10 @@ Function: language_uit::language_uit
 \*******************************************************************/
 
 language_uit::language_uit(
-  const cmdlinet &__cmdline,
+  const cmdlinet &cmdline,
   ui_message_handlert &_ui_message_handler):
   ui_message_handler(_ui_message_handler),
-  _cmdline(__cmdline)
+  _cmdline(cmdline)
 {
   set_message_handler(ui_message_handler);
 }
@@ -158,9 +158,7 @@ bool language_uit::typecheck()
 
   if(language_files.typecheck(symbol_table))
   {
-    if(get_ui()==ui_message_handlert::PLAIN)
-      std::cerr << "CONVERSION ERROR" << std::endl;
-
+    error() << "CONVERSION ERROR" << eom;
     return true;
   }
 
@@ -189,9 +187,7 @@ bool language_uit::final()
 
   if(language_files.final(symbol_table))
   {
-    if(get_ui()==ui_message_handlert::PLAIN)
-      std::cerr << "CONVERSION ERROR" << std::endl;
-
+    error() << "CONVERSION ERROR" << eom;
     return true;
   }
 
diff --git a/src/langapi/language_ui.h b/src/langapi/language_ui.h
index 90c1de3e5cb..b82507f4c75 100644
--- a/src/langapi/language_ui.h
+++ b/src/langapi/language_ui.h
@@ -23,7 +23,7 @@ class language_uit:public messaget
   symbol_tablet symbol_table;
 
   language_uit(
-    const cmdlinet &__cmdline,
+    const cmdlinet &cmdline,
     ui_message_handlert &ui_message_handler);
   virtual ~language_uit();
 
diff --git a/src/linking/linking.cpp b/src/linking/linking.cpp
index b66c0591b4b..173d5b2cf4c 100644
--- a/src/linking/linking.cpp
+++ b/src/linking/linking.cpp
@@ -936,11 +936,6 @@ bool linkingt::adjust_object_type_rec(
   else if(t1.id()!=t2.id())
   {
     // type classes do not match and can't be fixed
-    #ifdef DEBUG
-    str << "LINKING: cannot join " << t1.id() << " vs. " << t2.id();
-    debug_msg();
-    #endif
-
     return true;
   }
 
@@ -1041,11 +1036,6 @@ bool linkingt::adjust_object_type(
   const symbolt &new_symbol,
   bool &set_to_new)
 {
-  #ifdef DEBUG
-  str << "LINKING: trying to adjust types of " << old_symbol.name;
-  debug_msg();
-  #endif
-
   const typet &old_type=follow_tags_symbols(ns, old_symbol.type);
   const typet &new_type=follow_tags_symbols(ns, new_symbol.type);
 
@@ -1133,17 +1123,20 @@ void linkingt::duplicate_object_symbol(
       }
       else
       {
-        err_location(new_symbol.value);
-        error() << "error: conflicting initializers for variable \""
-                << old_symbol.name
-                << "\"" << '\n';
-        error() << "old value in module " << old_symbol.module
-                << " " << old_symbol.value.find_source_location() << '\n'
-                << expr_to_string(ns, old_symbol.name, tmp_old) << '\n';
-        error() << "new value in module " << new_symbol.module
-                << " " << new_symbol.value.find_source_location() << '\n'
-                << expr_to_string(ns, new_symbol.name, tmp_new) << eom;
-        throw 0;
+        warning().source_location=new_symbol.location;
+
+        warning() << "warning: conflicting initializers for"
+                  << " variable \"" << old_symbol.name << "\"\n";
+        warning() << "using old value in module "
+                  << old_symbol.module << " "
+                  << old_symbol.value.find_source_location() << '\n'
+                  << expr_to_string(ns, old_symbol.name, tmp_old)
+                  << '\n';
+        warning() << "ignoring new value in module "
+                  << new_symbol.module << " "
+                  << new_symbol.value.find_source_location() << '\n'
+                  << expr_to_string(ns, new_symbol.name, tmp_new)
+                  << eom;
       }
     }
   }
diff --git a/src/musketeer/fencer.cpp b/src/musketeer/fencer.cpp
index a787ce06393..4fc213908d4 100644
--- a/src/musketeer/fencer.cpp
+++ b/src/musketeer/fencer.cpp
@@ -87,9 +87,9 @@ void fence_weak_memory(
   {
     instrumenter.collect_cycles_by_SCCs(model);
     message.statistics() << "cycles collected: " << messaget::eom;
-    unsigned interesting_scc = 0;
-    unsigned total_cycles = 0;
-    for(unsigned i=0; i=4)
       {
         message.statistics() << "SCC #" << i << ": "
diff --git a/src/musketeer/musketeer_parse_options.cpp b/src/musketeer/musketeer_parse_options.cpp
index 707ec50bd0b..f2ca143683f 100644
--- a/src/musketeer/musketeer_parse_options.cpp
+++ b/src/musketeer/musketeer_parse_options.cpp
@@ -200,7 +200,6 @@ void goto_fence_inserter_parse_optionst::instrument_goto_program(
 
   // we add the library, as some analyses benefit
 
-  status() << "Adding CPROVER library" << eom;
   link_to_library(symbol_table, goto_functions, ui_message_handler);
 
   namespacet ns(symbol_table);
@@ -215,7 +214,10 @@ void goto_fence_inserter_parse_optionst::instrument_goto_program(
     if(cmdline.isset("remove-function-pointers"))
     {
       status() << "remove soundly function pointers" << eom;
-      remove_function_pointers(symbol_table, goto_functions,
+      remove_function_pointers(
+        get_message_handler(),
+        symbol_table,
+        goto_functions,
         cmdline.isset("pointer-check"));
     }
 
diff --git a/src/path-symex/path_symex.cpp b/src/path-symex/path_symex.cpp
index d8c5e0ea3de..eb58b330ab6 100644
--- a/src/path-symex/path_symex.cpp
+++ b/src/path-symex/path_symex.cpp
@@ -22,8 +22,6 @@ Author: Daniel Kroening, kroening@kroening.com
 #include "path_symex.h"
 #include "path_symex_class.h"
 
-// #define DEBUG
-
 #ifdef DEBUG
 #include 
 #endif
diff --git a/src/path-symex/path_symex_state.cpp b/src/path-symex/path_symex_state.cpp
index 2ce47fedc0f..3dfc319d6d6 100644
--- a/src/path-symex/path_symex_state.cpp
+++ b/src/path-symex/path_symex_state.cpp
@@ -18,8 +18,6 @@ Author: Daniel Kroening, kroening@kroening.com
 
 #include "path_symex_state.h"
 
-// #define DEBUG
-
 #ifdef DEBUG
 #include 
 #include 
diff --git a/src/path-symex/path_symex_state_read.cpp b/src/path-symex/path_symex_state_read.cpp
index df3621ee290..3aea2c24983 100644
--- a/src/path-symex/path_symex_state_read.cpp
+++ b/src/path-symex/path_symex_state_read.cpp
@@ -13,8 +13,6 @@ Author: Daniel Kroening, kroening@kroening.com
 
 #include "path_symex_state.h"
 
-// #define DEBUG
-
 #ifdef DEBUG
 #include 
 #include 
diff --git a/src/path-symex/var_map.cpp b/src/path-symex/var_map.cpp
index 8f18b3f9726..d981cf1cca9 100644
--- a/src/path-symex/var_map.cpp
+++ b/src/path-symex/var_map.cpp
@@ -14,8 +14,6 @@ Author: Daniel Kroening, kroening@kroening.com
 
 #include "var_map.h"
 
-// #define DEBUG
-
 /*******************************************************************\
 
 Function: var_mapt::var_infot::operator()
diff --git a/src/pointer-analysis/dereference.cpp b/src/pointer-analysis/dereference.cpp
index b21313f85bf..8638dff9e67 100644
--- a/src/pointer-analysis/dereference.cpp
+++ b/src/pointer-analysis/dereference.cpp
@@ -6,15 +6,12 @@ Author: Daniel Kroening, kroening@kroening.com
 
 \*******************************************************************/
 
-// #define DEBUG
-
 #ifdef DEBUG
 #include 
 #include 
 #endif
 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -279,11 +276,18 @@ exprt dereferencet::dereference_plus(
   const exprt &offset,
   const typet &type)
 {
+  exprt pointer=expr.op0();
+  exprt integer=expr.op1();
+
+  // need not be binary
   if(expr.operands().size()>2)
-    return dereference_rec(make_binary(expr), offset, type);
+  {
+    assert(expr.op0().type().id()==ID_pointer);
 
-  // binary
-  exprt pointer=expr.op0(), integer=expr.op1();
+    exprt::operandst plus_ops(
+      ++expr.operands().begin(), expr.operands().end());
+    integer.operands().swap(plus_ops);
+  }
 
   if(ns.follow(integer.type()).id()==ID_pointer)
     std::swap(pointer, integer);
diff --git a/src/pointer-analysis/value_set.cpp b/src/pointer-analysis/value_set.cpp
index 629a25509d6..1a6c639ff92 100644
--- a/src/pointer-analysis/value_set.cpp
+++ b/src/pointer-analysis/value_set.cpp
@@ -799,8 +799,7 @@ void value_sett::get_value_set_rec(
         static_cast(expr.find("#type"));
 
       dynamic_object_exprt dynamic_object(dynamic_type);
-      dynamic_object.instance()=
-        from_integer(location_number, typet(ID_natural));
+      dynamic_object.set_instance(location_number);
       dynamic_object.valid()=true_exprt();
 
       insert(dest, dynamic_object, 0);
@@ -812,8 +811,7 @@ void value_sett::get_value_set_rec(
       assert(expr_type.id()==ID_pointer);
 
       dynamic_object_exprt dynamic_object(expr_type.subtype());
-      dynamic_object.instance()=
-        from_integer(location_number, typet(ID_natural));
+      dynamic_object.set_instance(location_number);
       dynamic_object.valid()=true_exprt();
 
       insert(dest, dynamic_object, 0);
@@ -897,7 +895,7 @@ void value_sett::get_value_set_rec(
 
     const std::string prefix=
       "value_set::dynamic_object"+
-      dynamic_object.instance().get_string(ID_value);
+      std::to_string(dynamic_object.get_instance());
 
     // first try with suffix
     const std::string full_name=prefix+suffix;
@@ -1392,7 +1390,7 @@ void value_sett::do_free(
   const object_map_dt &object_map=value_set.read();
 
   // find out which *instances* interest us
-  expr_sett to_mark;
+  dynamic_object_id_sett to_mark;
 
   for(object_map_dt::const_iterator
       it=object_map.begin();
@@ -1407,7 +1405,7 @@ void value_sett::do_free(
         to_dynamic_object_expr(object);
 
       if(dynamic_object.valid().is_true())
-        to_mark.insert(dynamic_object.instance());
+        to_mark.insert(dynamic_object.get_instance());
     }
   }
 
@@ -1433,10 +1431,10 @@ void value_sett::do_free(
 
       if(object.id()==ID_dynamic_object)
       {
-        const exprt &instance=
-          to_dynamic_object_expr(object).instance();
+        const dynamic_object_exprt &dynamic_object=
+          to_dynamic_object_expr(object);
 
-        if(to_mark.count(instance)==0)
+        if(to_mark.count(dynamic_object.get_instance())==0)
           set(new_object_map, o_it);
         else
         {
@@ -1507,7 +1505,7 @@ void value_sett::assign_rec(
 
     const std::string name=
       "value_set::dynamic_object"+
-      dynamic_object.instance().get_string(ID_value);
+      std::to_string(dynamic_object.get_instance());
 
     entryt &e=get_entry(entryt(name, suffix), lhs.type(), ns);
 
diff --git a/src/pointer-analysis/value_set.h b/src/pointer-analysis/value_set.h
index 486b55e998b..51bf74d48f2 100644
--- a/src/pointer-analysis/value_set.h
+++ b/src/pointer-analysis/value_set.h
@@ -115,6 +115,8 @@ class value_sett
 
   typedef std::set expr_sett;
 
+  typedef std::set dynamic_object_id_sett;
+
   #ifdef USE_DSTRING
   typedef std::map valuest;
   #else
diff --git a/src/pointer-analysis/value_set_dereference.cpp b/src/pointer-analysis/value_set_dereference.cpp
index 98e6ab2cb2a..04598ac67fa 100644
--- a/src/pointer-analysis/value_set_dereference.cpp
+++ b/src/pointer-analysis/value_set_dereference.cpp
@@ -6,8 +6,6 @@ Author: Daniel Kroening, kroening@kroening.com
 
 \*******************************************************************/
 
-// #define DEBUG
-
 #ifdef DEBUG
 #include 
 #endif
diff --git a/src/pointer-analysis/value_set_fi.cpp b/src/pointer-analysis/value_set_fi.cpp
index 55542296c48..0fbcd7dec00 100644
--- a/src/pointer-analysis/value_set_fi.cpp
+++ b/src/pointer-analysis/value_set_fi.cpp
@@ -727,9 +727,8 @@ void value_set_fit::get_value_set_rec(
 
       dynamic_object_exprt dynamic_object(dynamic_type);
       // let's make up a `unique' number for this object...
-      dynamic_object.instance()=
-        from_integer(
-          (from_function << 16) | from_target_index, typet(ID_natural));
+      dynamic_object.set_instance(
+        (from_function << 16) | from_target_index);
       dynamic_object.valid()=true_exprt();
 
       insert(dest, dynamic_object, 0);
@@ -742,9 +741,8 @@ void value_set_fit::get_value_set_rec(
       assert(expr.type().id()==ID_pointer);
 
       dynamic_object_exprt dynamic_object(expr.type().subtype());
-      dynamic_object.instance()=
-        from_integer(
-          (from_function << 16) | from_target_index, typet(ID_natural));
+      dynamic_object.set_instance(
+        (from_function << 16) | from_target_index);
       dynamic_object.valid()=true_exprt();
 
       insert(dest, dynamic_object, 0);
@@ -776,7 +774,7 @@ void value_set_fit::get_value_set_rec(
 
     const std::string name=
       "value_set::dynamic_object"+
-      dynamic_object.instance().get_string(ID_value)+
+      std::to_string(dynamic_object.get_instance())+
       suffix;
 
     // look it up
@@ -1322,7 +1320,7 @@ void value_set_fit::do_free(
   const object_map_dt &object_map=value_set.read();
 
   // find out which *instances* interest us
-  expr_sett to_mark;
+  dynamic_object_id_sett to_mark;
 
   forall_objects(it, object_map)
   {
@@ -1334,7 +1332,7 @@ void value_set_fit::do_free(
         to_dynamic_object_expr(object);
 
       if(dynamic_object.valid().is_true())
-        to_mark.insert(dynamic_object.instance());
+        to_mark.insert(dynamic_object.get_instance());
     }
   }
 
@@ -1357,10 +1355,10 @@ void value_set_fit::do_free(
 
       if(object.id()==ID_dynamic_object)
       {
-        const exprt &instance=
-          to_dynamic_object_expr(object).instance();
+        const dynamic_object_exprt &dynamic_object=
+          to_dynamic_object_expr(object);
 
-        if(to_mark.count(instance)==0)
+        if(to_mark.count(dynamic_object.get_instance())==0)
           set(new_object_map, o_it);
         else
         {
@@ -1452,7 +1450,7 @@ void value_set_fit::assign_rec(
 
     const std::string name=
       "value_set::dynamic_object"+
-      dynamic_object.instance().get_string(ID_value);
+      std::to_string(dynamic_object.get_instance());
 
     if(make_union(get_entry(name, suffix).object_map, values_rhs))
       changed = true;
diff --git a/src/pointer-analysis/value_set_fi.h b/src/pointer-analysis/value_set_fi.h
index 5b76d0f48d9..13defa545ae 100644
--- a/src/pointer-analysis/value_set_fi.h
+++ b/src/pointer-analysis/value_set_fi.h
@@ -155,6 +155,8 @@ class value_set_fit
 
   typedef std::unordered_set expr_sett;
 
+  typedef std::unordered_set dynamic_object_id_sett;
+
   #ifdef USE_DSTRING
   typedef std::map valuest;
   typedef std::set flatten_seent;
diff --git a/src/pointer-analysis/value_set_fivr.cpp b/src/pointer-analysis/value_set_fivr.cpp
index 582fe015dd3..e06d73b245b 100644
--- a/src/pointer-analysis/value_set_fivr.cpp
+++ b/src/pointer-analysis/value_set_fivr.cpp
@@ -857,9 +857,8 @@ void value_set_fivrt::get_value_set_rec(
 
       dynamic_object_exprt dynamic_object(dynamic_type);
       // let's make up a `unique' number for this object...
-      dynamic_object.instance()=
-        from_integer(
-          (from_function << 16) | from_target_index, typet(ID_natural));
+      dynamic_object.set_instance(
+        (from_function << 16) | from_target_index);
       dynamic_object.valid()=true_exprt();
 
       insert_from(dest, dynamic_object, 0);
@@ -873,9 +872,8 @@ void value_set_fivrt::get_value_set_rec(
 
       dynamic_object_exprt dynamic_object(expr.type().subtype());
       // let's make up a unique number for this object...
-      dynamic_object.instance()=
-        from_integer(
-          (from_function << 16) | from_target_index, typet(ID_natural));
+      dynamic_object.set_instance(
+        (from_function << 16) | from_target_index);
       dynamic_object.valid()=true_exprt();
 
       insert_from(dest, dynamic_object, 0);
@@ -902,7 +900,7 @@ void value_set_fivrt::get_value_set_rec(
 
     const std::string name=
       "value_set::dynamic_object"+
-      dynamic_object.instance().get_string(ID_value)+
+      std::to_string(dynamic_object.get_instance())+
       suffix;
 
     // look it up
@@ -1446,7 +1444,7 @@ void value_set_fivrt::do_free(
   const object_map_dt &object_map=value_set.read();
 
   // find out which *instances* interest us
-  expr_sett to_mark;
+  dynamic_object_id_sett to_mark;
 
   forall_objects(it, object_map)
   {
@@ -1458,7 +1456,7 @@ void value_set_fivrt::do_free(
         to_dynamic_object_expr(object);
 
       if(dynamic_object.valid().is_true())
-        to_mark.insert(dynamic_object.instance());
+        to_mark.insert(dynamic_object.get_instance());
     }
   }
 
@@ -1481,10 +1479,10 @@ void value_set_fivrt::do_free(
 
       if(object.id()==ID_dynamic_object)
       {
-        const exprt &instance=
-          to_dynamic_object_expr(object).instance();
+        const dynamic_object_exprt &dynamic_object=
+          to_dynamic_object_expr(object);
 
-        if(to_mark.count(instance)==0)
+        if(to_mark.count(dynamic_object.get_instance())==0)
           set(new_object_map, o_it);
         else
         {
@@ -1590,7 +1588,7 @@ void value_set_fivrt::assign_rec(
 
     const std::string name=
       "value_set::dynamic_object"+
-      dynamic_object.instance().get_string(ID_value);
+      std::to_string(dynamic_object.get_instance());
 
     entryt &temp_entry=get_temporary_entry(name, suffix);
 
diff --git a/src/pointer-analysis/value_set_fivr.h b/src/pointer-analysis/value_set_fivr.h
index 5a96e537e77..e12563252ae 100644
--- a/src/pointer-analysis/value_set_fivr.h
+++ b/src/pointer-analysis/value_set_fivr.h
@@ -216,6 +216,8 @@ class value_set_fivrt
 
   typedef std::unordered_set expr_sett;
 
+  typedef std::unordered_set dynamic_object_id_sett;
+
   #ifdef USE_DSTRING
   typedef std::map valuest;
   typedef std::unordered_set flatten_seent;
diff --git a/src/pointer-analysis/value_set_fivrns.cpp b/src/pointer-analysis/value_set_fivrns.cpp
index 41907d54cfb..4591bdd938d 100644
--- a/src/pointer-analysis/value_set_fivrns.cpp
+++ b/src/pointer-analysis/value_set_fivrns.cpp
@@ -631,9 +631,8 @@ void value_set_fivrnst::get_value_set_rec(
 
       dynamic_object_exprt dynamic_object(dynamic_type);
       // let's make up a `unique' number for this object...
-      dynamic_object.instance()=
-        from_integer(
-          (from_function << 16) | from_target_index, typet(ID_natural));
+      dynamic_object.set_instance(
+        (from_function << 16) | from_target_index);
       dynamic_object.valid()=true_exprt();
 
       insert_from(dest, dynamic_object, 0);
@@ -647,9 +646,8 @@ void value_set_fivrnst::get_value_set_rec(
 
       dynamic_object_exprt dynamic_object(expr.type().subtype());
       // let's make up a unique number for this object...
-      dynamic_object.instance()=
-        from_integer(
-          (from_function << 16) | from_target_index, typet(ID_natural));
+      dynamic_object.set_instance(
+        (from_function << 16) | from_target_index);
       dynamic_object.valid()=true_exprt();
 
       insert_from(dest, dynamic_object, 0);
@@ -676,7 +674,7 @@ void value_set_fivrnst::get_value_set_rec(
 
     const std::string name=
       "value_set::dynamic_object"+
-      dynamic_object.instance().get_string(ID_value)+
+      std::to_string(dynamic_object.get_instance())+
       suffix;
 
     // look it up
@@ -1105,7 +1103,7 @@ void value_set_fivrnst::do_free(
   const object_map_dt &object_map=value_set.read();
 
   // find out which *instances* interest us
-  expr_sett to_mark;
+  dynamic_object_id_sett to_mark;
 
   forall_objects(it, object_map)
   {
@@ -1117,7 +1115,7 @@ void value_set_fivrnst::do_free(
         to_dynamic_object_expr(object);
 
       if(dynamic_object.valid().is_true())
-        to_mark.insert(dynamic_object.instance());
+        to_mark.insert(dynamic_object.get_instance());
     }
   }
 
@@ -1140,10 +1138,10 @@ void value_set_fivrnst::do_free(
 
       if(object.id()==ID_dynamic_object)
       {
-        const exprt &instance=
-          to_dynamic_object_expr(object).instance();
+        const dynamic_object_exprt &dynamic_object=
+          to_dynamic_object_expr(object);
 
-        if(to_mark.count(instance)==0)
+        if(to_mark.count(dynamic_object.get_instance())==0)
           set(new_object_map, o_it);
         else
         {
@@ -1225,7 +1223,7 @@ void value_set_fivrnst::assign_rec(
 
     const std::string name=
       "value_set::dynamic_object"+
-      dynamic_object.instance().get_string(ID_value);
+      std::to_string(dynamic_object.get_instance());
 
     entryt &temp_entry = get_temporary_entry(name, suffix);
 
diff --git a/src/pointer-analysis/value_set_fivrns.h b/src/pointer-analysis/value_set_fivrns.h
index c1d826f2550..f3afc204ef2 100644
--- a/src/pointer-analysis/value_set_fivrns.h
+++ b/src/pointer-analysis/value_set_fivrns.h
@@ -216,6 +216,8 @@ class value_set_fivrnst
 
   typedef std::unordered_set expr_sett;
 
+  typedef std::unordered_set dynamic_object_id_sett;
+
   #ifdef USE_DSTRING
   typedef std::map valuest;
   #else
diff --git a/src/solvers/flattening/arrays.cpp b/src/solvers/flattening/arrays.cpp
index 9c710fc3737..9f72a8e3475 100644
--- a/src/solvers/flattening/arrays.cpp
+++ b/src/solvers/flattening/arrays.cpp
@@ -6,8 +6,6 @@ Author: Daniel Kroening, kroening@kroening.com
 
 \*******************************************************************/
 
-// #define DEBUG
-
 #include 
 #include 
 
diff --git a/src/solvers/flattening/boolbv.cpp b/src/solvers/flattening/boolbv.cpp
index f5e9aad9f8b..aaa63e69fd2 100644
--- a/src/solvers/flattening/boolbv.cpp
+++ b/src/solvers/flattening/boolbv.cpp
@@ -27,8 +27,6 @@ Author: Daniel Kroening, kroening@kroening.com
 
 #include "../floatbv/float_utils.h"
 
-// #define DEBUG
-
 /*******************************************************************\
 
 Function: boolbvt::literal
@@ -144,9 +142,6 @@ const bvt &boolbvt::convert_bv(const exprt &expr)
     bv_cache.insert(std::make_pair(expr, bvt()));
   if(!cache_result.second)
   {
-    #ifdef DEBUG
-    std::cout << "Cache hit on " << expr << "\n";
-    #endif
     return cache_result.first->second;
   }
 
@@ -205,10 +200,6 @@ Function: boolbvt::convert_bitvector
 
 bvt boolbvt::convert_bitvector(const exprt &expr)
 {
-  #ifdef DEBUG
-  std::cout << "BV: " << expr.pretty() << std::endl;
-  #endif
-
   if(expr.type().id()==ID_bool)
   {
     bvt bv;
diff --git a/src/solvers/flattening/boolbv_floatbv_op.cpp b/src/solvers/flattening/boolbv_floatbv_op.cpp
index 087faa0485a..e4926dc617e 100644
--- a/src/solvers/flattening/boolbv_floatbv_op.cpp
+++ b/src/solvers/flattening/boolbv_floatbv_op.cpp
@@ -138,7 +138,7 @@ bvt boolbvt::convert_floatbv_op(const exprt &expr)
     else if(expr.id()==ID_floatbv_rem)
       return float_utils.rem(bv0, bv1);
     else
-      assert(false);
+      throw "unexpected operator "+expr.id_string();
   }
   else if(type.id()==ID_vector || type.id()==ID_complex)
   {
diff --git a/src/solvers/flattening/boolbv_get.cpp b/src/solvers/flattening/boolbv_get.cpp
index 3e74ec872c1..943ef98b19c 100644
--- a/src/solvers/flattening/boolbv_get.cpp
+++ b/src/solvers/flattening/boolbv_get.cpp
@@ -17,8 +17,6 @@ Author: Daniel Kroening, kroening@kroening.com
 #include "boolbv.h"
 #include "boolbv_type.h"
 
-// #define DEBUG
-
 /*******************************************************************\
 
 Function: boolbvt::get
diff --git a/src/solvers/flattening/boolbv_map.cpp b/src/solvers/flattening/boolbv_map.cpp
index dbbb097e7b2..6c6e647a31c 100644
--- a/src/solvers/flattening/boolbv_map.cpp
+++ b/src/solvers/flattening/boolbv_map.cpp
@@ -13,8 +13,6 @@ Author: Daniel Kroening, kroening@kroening.com
 #include "boolbv_map.h"
 #include "boolbv_width.h"
 
-// #define DEBUG
-
 #ifdef DEBUG
 #include 
 #endif
diff --git a/src/solvers/flattening/equality.cpp b/src/solvers/flattening/equality.cpp
index 208a4510a35..63ca7e2e147 100644
--- a/src/solvers/flattening/equality.cpp
+++ b/src/solvers/flattening/equality.cpp
@@ -6,8 +6,6 @@ Author: Daniel Kroening, kroening@kroening.com
 
 \*******************************************************************/
 
-// #define DEBUG
-
 #ifdef DEBUG
 #include 
 #endif
@@ -110,11 +108,6 @@ literalt equalityt::equality2(const exprt &e1, const exprt &e2)
       l=result->second;
   }
 
-  #ifdef DEBUG
-  std::cout << "EQUALITY " << l << "<=>"
-            << e1 << "=" << e2 << std::endl;
-  #endif
-
   return l;
 }
 
diff --git a/src/solvers/flattening/functions.cpp b/src/solvers/flattening/functions.cpp
index 37380aa323b..6b23229c958 100644
--- a/src/solvers/flattening/functions.cpp
+++ b/src/solvers/flattening/functions.cpp
@@ -6,8 +6,6 @@ Author: Daniel Kroening, kroening@kroening.com
 
 \*******************************************************************/
 
-// #define DEBUG
-
 #include 
 
 #include 
diff --git a/src/solvers/floatbv/float_utils.cpp b/src/solvers/floatbv/float_utils.cpp
index c277e51e6b0..a772ae0b8a7 100644
--- a/src/solvers/floatbv/float_utils.cpp
+++ b/src/solvers/floatbv/float_utils.cpp
@@ -206,7 +206,7 @@ bvt float_utilst::to_integer(
     return result;
   }
   else
-    assert(0);
+    throw "unsupported rounding mode";
 }
 
 /*******************************************************************\
diff --git a/src/solvers/miniBDD/Makefile b/src/solvers/miniBDD/Makefile
index aa4d2f532df..55b6a0ed86c 100644
--- a/src/solvers/miniBDD/Makefile
+++ b/src/solvers/miniBDD/Makefile
@@ -16,7 +16,7 @@ test_miniBDD: miniBDD.o test_miniBDD.o
 	g++ $(CPLUSFLAGS) miniBDD.o test_miniBDD.o -o test_miniBDD
 
 clean:
-	rm -f miniBDD.o test_miniBDD.o test_miniBDD
+	$(RM) miniBDD.o test_miniBDD.o test_miniBDD
 
 miniBDD.tgz: miniBDD.cpp miniBDD.inc miniBDD.h test_miniBDD.cpp Makefile
 	tar cvfz miniBDD.tgz miniBDD.cpp miniBDD.inc \
diff --git a/src/solvers/prop/prop_conv.cpp b/src/solvers/prop/prop_conv.cpp
index 01ae3fcd841..33a572191c0 100644
--- a/src/solvers/prop/prop_conv.cpp
+++ b/src/solvers/prop/prop_conv.cpp
@@ -18,8 +18,6 @@ Author: Daniel Kroening, kroening@kroening.com
 #include "prop_conv.h"
 #include "literal_expr.h"
 
-// #define DEBUG
-
 /*******************************************************************\
 
 Function: prop_convt::is_in_conflict
diff --git a/src/solvers/sat/satcheck_limmat.cpp b/src/solvers/sat/satcheck_limmat.cpp
index a1aadbbff39..a8393cf30e8 100644
--- a/src/solvers/sat/satcheck_limmat.cpp
+++ b/src/solvers/sat/satcheck_limmat.cpp
@@ -16,8 +16,6 @@ extern "C"
 #include "limmat.h"
 }
 
-// #define DEBUG
-
 /*******************************************************************\
 
 Function: satcheck_limmatt::satcheck_limmatt
diff --git a/src/solvers/sat/satcheck_zchaff.cpp b/src/solvers/sat/satcheck_zchaff.cpp
index 5a94615e221..6697d6b3c6c 100644
--- a/src/solvers/sat/satcheck_zchaff.cpp
+++ b/src/solvers/sat/satcheck_zchaff.cpp
@@ -13,8 +13,6 @@ Author: Daniel Kroening, kroening@kroening.com
 
 #include 
 
-// #define DEBUG
-
 /*******************************************************************\
 
 Function: satcheck_zchaff_baset::satcheck_zchaff_baset
diff --git a/src/symex/path_search.cpp b/src/symex/path_search.cpp
index fe34b04cc66..fcbaebbc39a 100644
--- a/src/symex/path_search.cpp
+++ b/src/symex/path_search.cpp
@@ -6,6 +6,7 @@ Author: Daniel Kroening, kroening@kroening.com
 
 \*******************************************************************/
 
+#include 
 #include 
 
 #include 
@@ -315,8 +316,10 @@ Function: path_searcht::drop_state
 
 \*******************************************************************/
 
-bool path_searcht::drop_state(const statet &state) const
+bool path_searcht::drop_state(const statet &state)
 {
+  goto_programt::const_targett pc=state.get_instruction();
+
   // depth limit
   if(depth_limit_set && state.get_depth()>depth_limit)
     return true;
@@ -345,6 +348,22 @@ bool path_searcht::drop_state(const statet &state) const
         return true;
   }
 
+  if(pc->is_assume() &&
+     simplify_expr(pc->guard, ns).is_false())
+  {
+    debug() << "aborting path on assume(false) at "
+            << pc->source_location
+            << " thread " << state.get_current_thread();
+
+    const irep_idt &c=pc->source_location.get_comment();
+    if(!c.empty())
+      debug() << ": " << c;
+
+    debug() << eom;
+
+    return true;
+  }
+
   return false;
 }
 
diff --git a/src/symex/path_search.h b/src/symex/path_search.h
index b72588c593c..49fc621b84e 100644
--- a/src/symex/path_search.h
+++ b/src/symex/path_search.h
@@ -120,7 +120,7 @@ class path_searcht:public safety_checkert
   bool is_feasible(statet &state);
   void do_show_vcc(statet &state);
 
-  bool drop_state(const statet &state) const;
+  bool drop_state(const statet &state);
 
   void report_statistics();
 
diff --git a/src/symex/symex_parse_options.cpp b/src/symex/symex_parse_options.cpp
index 04135b96d9c..8001a5b8155 100644
--- a/src/symex/symex_parse_options.cpp
+++ b/src/symex/symex_parse_options.cpp
@@ -179,7 +179,7 @@ int symex_parse_optionst::doit()
 
   goto_model.set_message_handler(get_message_handler());
 
-  if(goto_model(cmdline.args))
+  if(goto_model(cmdline))
     return 6;
 
   if(process_goto_program(options))
@@ -355,7 +355,6 @@ bool symex_parse_optionst::process_goto_program(const optionst &options)
   try
   {
     // we add the library
-    status() << "Adding CPROVER library" << eom;
     link_to_library(goto_model, ui_message_handler);
 
     // do partial inlining
@@ -387,7 +386,7 @@ bool symex_parse_optionst::process_goto_program(const optionst &options)
     if(cmdline.isset("drop-unused-functions"))
     {
       // Entry point will have been set before and function pointers removed
-      status() << "Removing Unused Functions" << eom;
+      status() << "Removing unused functions" << eom;
       remove_unused_functions(goto_model.goto_functions, ui_message_handler);
     }
 
@@ -691,7 +690,6 @@ void symex_parse_optionst::help()
     " --stop-on-fail               stop analysis once a failed property is detected\n"
     // NOLINTNEXTLINE(whitespace/line_length)
     " --trace                      give a counterexample trace for failed properties\n"
-    " --drop-unused-functions      drop functions trivially unreachable from main function\n" // NOLINT(*)
     "\n"
     "Frontend options:\n"
     " -I path                      set include path (C/C++)\n"
@@ -706,6 +704,7 @@ void symex_parse_optionst::help()
     " --show-parse-tree            show parse tree\n"
     " --show-symbol-table          show symbol table\n"
     HELP_SHOW_GOTO_FUNCTIONS
+    " --drop-unused-functions      drop functions trivially unreachable from main function\n" // NOLINT(*)
     " --ppc-macos                  set MACOS/PPC architecture\n"
     " --mm model                   set memory model (default: sc)\n"
     " --arch                       set architecture (default: "
@@ -739,5 +738,6 @@ void symex_parse_optionst::help()
     "Other options:\n"
     " --version                    show version and exit\n"
     " --xml-ui                     use XML-formatted output\n"
+    " --verbosity #                verbosity level\n"
     "\n";
 }
diff --git a/src/util/Makefile b/src/util/Makefile
index 61cff93b9f0..4826d142b36 100644
--- a/src/util/Makefile
+++ b/src/util/Makefile
@@ -12,7 +12,7 @@ SRC = arith_tools.cpp base_type.cpp cmdline.cpp config.cpp symbol_table.cpp \
       rational.cpp options.cpp dstring.cpp \
       find_symbols.cpp rational_tools.cpp ui_message.cpp simplify_utils.cpp \
       time_stopping.cpp symbol.cpp irep_hash_container.cpp cout_message.cpp \
-      type_eq.cpp guard.cpp array_name.cpp message_stream.cpp \
+      type_eq.cpp guard.cpp array_name.cpp \
       substitute.cpp decision_procedure.cpp union_find.cpp \
       xml.cpp xml_irep.cpp xml_expr.cpp std_types.cpp std_code.cpp \
       format_constant.cpp find_macros.cpp ref_expr_set.cpp std_expr.cpp \
diff --git a/src/util/cout_message.cpp b/src/util/cout_message.cpp
index af315c696c5..393ec62432f 100644
--- a/src/util/cout_message.cpp
+++ b/src/util/cout_message.cpp
@@ -211,5 +211,6 @@ void gcc_message_handlert::print(
   const std::string &message)
 {
   // gcc appears to send everything to cerr
-  std::cerr << message << '\n' << std::flush;
+  if(verbosity>=level)
+    std::cerr << message << '\n' << std::flush;
 }
diff --git a/src/util/expr_util.cpp b/src/util/expr_util.cpp
index f5abbc06c28..d5a28e4f5fa 100644
--- a/src/util/expr_util.cpp
+++ b/src/util/expr_util.cpp
@@ -55,13 +55,19 @@ exprt make_binary(const exprt &expr)
   if(operands.size()<=2)
     return expr;
 
+  // types must be identical for make_binary to be safe to use
+  const typet &type=expr.type();
+
   exprt previous=operands.front();
+  assert(previous.type()==type);
 
   for(exprt::operandst::const_iterator
       it=++operands.begin();
       it!=operands.end();
       ++it)
   {
+    assert(it->type()==type);
+
     exprt tmp=expr;
     tmp.operands().clear();
     tmp.operands().resize(2);
diff --git a/src/util/file_util.cpp b/src/util/file_util.cpp
index 50dc06473f4..18634240141 100644
--- a/src/util/file_util.cpp
+++ b/src/util/file_util.cpp
@@ -16,6 +16,7 @@ Date: January 2012
     defined(__unix__) || \
     defined(__CYGWIN__) || \
     defined(__MACH__)
+#include 
 #include 
 #include 
 #include 
@@ -124,8 +125,13 @@ void delete_directory(const std::string &path)
       // Needed for Alpine Linux
       if(strcmp(ent->d_name, ".")==0 || strcmp(ent->d_name, "..")==0)
         continue;
+
       std::string sub_path=path+"/"+ent->d_name;
-      if(ent->d_type==DT_DIR)
+
+      struct stat stbuf;
+      stat(sub_path.c_str(), &stbuf);
+
+      if(S_ISDIR(stbuf.st_mode))
         delete_directory(sub_path);
       else
         remove(sub_path.c_str());
diff --git a/src/util/irep.h b/src/util/irep.h
index af0b68ac26e..6dd15df0983 100644
--- a/src/util/irep.h
+++ b/src/util/irep.h
@@ -283,11 +283,7 @@ class irept
 
     void clear()
     {
-      #ifdef USE_DSTRING
       data.clear();
-      #else
-      data="";
-      #endif
       sub.clear();
       named_sub.clear();
       comments.clear();
diff --git a/src/util/irep_ids.txt b/src/util/irep_ids.txt
index 1958522eaee..5e364d97ea0 100644
--- a/src/util/irep_ids.txt
+++ b/src/util/irep_ids.txt
@@ -251,6 +251,7 @@ concatenation
 infinity
 return_type
 typedef
+C_typedef #typedef
 extern
 static
 auto
@@ -681,7 +682,6 @@ read
 write
 native
 final
-_start
 compound_literal
 custom_bv
 custom_unsignedbv
diff --git a/src/util/json_irep.cpp b/src/util/json_irep.cpp
index 403247c1d04..2740228d1db 100644
--- a/src/util/json_irep.cpp
+++ b/src/util/json_irep.cpp
@@ -164,8 +164,8 @@ void json_irept::convert_from_json(const jsont &in, irept &out) const
   }
 
   for(const auto &named_sub : in["namedSub"].object)
-    convert_from_json(named_sub.second, out.get_named_sub()[named_sub.first]);
+    convert_from_json(named_sub.second, out.add(named_sub.first));
 
   for(const auto &comment : in["comment"].object)
-    convert_from_json(comment.second, out.get_comments()[comment.first]);
+    convert_from_json(comment.second, out.add(comment.first));
 }
diff --git a/src/util/message_stream.cpp b/src/util/message_stream.cpp
deleted file mode 100644
index 347d87915d7..00000000000
--- a/src/util/message_stream.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/*******************************************************************\
-
-Module:
-
-Author: Daniel Kroening, kroening@kroening.com
-
-\*******************************************************************/
-
-#include 
-
-#include "prefix.h"
-#include "message_stream.h"
-
-/*******************************************************************\
-
-Function: legacy_message_streamt::error_parse_line
-
-  Inputs:
-
- Outputs:
-
- Purpose:
-
-\*******************************************************************/
-
-void legacy_message_streamt::error_parse_line(
-  unsigned level,
-  const std::string &line)
-{
-  std::string error_msg=line;
-
-  if(has_prefix(line, "file "))
-  {
-    const char *tptr=line.c_str();
-    int state=0;
-    std::string file, line_no, column, _error_msg, function;
-
-    tptr+=5;
-
-    char previous=0;
-
-    while(*tptr!=0)
-    {
-      if(strncmp(tptr, " line ", 6)==0 && state!=4)
-      {
-        state=1;
-        tptr+=6;
-        continue;
-      }
-      else if(strncmp(tptr, " column ", 8)==0 && state!=4)
-      {
-        state=2;
-        tptr+=8;
-        continue;
-      }
-      else if(strncmp(tptr, " function ", 10)==0 && state!=4)
-      {
-        state=3;
-        tptr+=10;
-        continue;
-      }
-      else if(*tptr==':' && state!=4)
-      {
-        if(tptr[1]==' ' && previous!=':')
-        {
-          state=4;
-          tptr++;
-          while(*tptr==' ') tptr++;
-          continue;
-        }
-      }
-
-      if(state==0) // file
-        file+=*tptr;
-      else if(state==1) // line number
-        line_no+=*tptr;
-      else if(state==2) // column
-        column+=*tptr;
-      else if(state==3) // function
-        function+=*tptr;
-      else if(state==4) // error message
-        _error_msg+=*tptr;
-
-      previous=*tptr;
-
-      tptr++;
-    }
-
-    if(state==4)
-    {
-      saved_error_location.id(irep_idt());
-      saved_error_location.set_line(line_no);
-      saved_error_location.set_file(file);
-      saved_error_location.set_column(column);
-      error_msg=_error_msg;
-      saved_error_location.set_function(function);
-    }
-  }
-  else if(has_prefix(line, "In file included from "))
-  {
-  }
-  else
-  {
-    const char *tptr=line.c_str();
-    int state=0;
-    std::string file, line_no;
-
-    while(*tptr!=0)
-    {
-      if(state==0)
-      {
-        if(*tptr==':')
-          state++;
-        else
-          file+=*tptr;
-      }
-      else if(state==1)
-      {
-        if(*tptr==':')
-          state++;
-        else if(isdigit(*tptr))
-          line_no+=*tptr;
-        else
-          state=3;
-      }
-
-      tptr++;
-    }
-
-    if(state==2)
-    {
-      saved_error_location.id(irep_idt());
-      saved_error_location.set_line(line_no);
-      saved_error_location.set_file(file);
-      saved_error_location.set_function("");
-      saved_error_location.set_column("");
-    }
-  }
-
-  if(message_handler!=NULL)
-    message_handler->print(
-      level, error_msg, sequence_number++, saved_error_location);
-}
-
-/*******************************************************************\
-
-Function: legacy_message_streamt::error_parse
-
-  Inputs:
-
- Outputs:
-
- Purpose:
-
-\*******************************************************************/
-
-void legacy_message_streamt::error_parse(
-  unsigned level,
-  const std::string &error)
-{
-  const char *tptr=error.c_str();
-
-  std::string line;
-
-  while(true)
-  {
-    switch(*tptr)
-    {
-     case 0: return;
-     case '\n':
-      error_parse_line(level, line);
-      line.clear();
-      break;
-
-     case '\r': break;
-     default:
-      line+=*tptr;
-    }
-
-    tptr++;
-  }
-}
diff --git a/src/util/message_stream.h b/src/util/message_stream.h
deleted file mode 100644
index 4b3fc48bb7d..00000000000
--- a/src/util/message_stream.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*******************************************************************\
-
-Module:
-
-Author: Daniel Kroening, kroening@kroening.com
-
-\*******************************************************************/
-
-#ifndef CPROVER_UTIL_MESSAGE_STREAM_H
-#define CPROVER_UTIL_MESSAGE_STREAM_H
-
-#include 
-
-#include "message.h"
-#include "expr.h"
-
-// deprecated; use warning(), error(), etc. streams in messaget
-
-class legacy_message_streamt:public message_clientt
-{
-public:
-  explicit legacy_message_streamt(message_handlert &_message_handler):
-    message_clientt(_message_handler),
-    error_found(false),
-    saved_error_location(static_cast(get_nil_irep())),
-    sequence_number(1)
-  {
-  }
-
-  virtual ~legacy_message_streamt() { }
-
-  // overload to use language specific syntax
-  virtual std::string to_string(const exprt &expr) { return expr.pretty(); }
-  virtual std::string to_string(const typet &type) { return type.pretty(); }
-
-  void err_location(const exprt &expr)
-  { saved_error_location=expr.find_source_location(); }
-  void err_location(const typet &type)
-  { saved_error_location=type.source_location(); }
-  void err_location(const irept &irep)
-  {
-    saved_error_location=
-      static_cast(irep.find(ID_C_source_location));
-  }
-  void err_location(const source_locationt &_location)
-  { saved_error_location=_location; }
-
-  void error_msg(const std::string &message)
-  {
-    send_msg(1, message);
-  }
-
-  void warning_msg(const std::string &message)
-  {
-    send_msg(2, message);
-  }
-
-  void statistics_msg(const std::string &message)
-  {
-    send_msg(8, message);
-  }
-
-  void debug_msg(const std::string &message)
-  {
-    send_msg(9, message);
-  }
-
-  void error_msg()
-  {
-    send_msg(1, str.str());
-    clear_err();
-    sequence_number++;
-  }
-
-  void warning_msg()
-  {
-    send_msg(2, str.str());
-    clear_err();
-    sequence_number++;
-  }
-
-  void status_msg()
-  {
-    send_msg(6, str.str());
-    clear_err();
-    sequence_number++;
-  }
-
-  void statistics_msg()
-  {
-    send_msg(8, str.str());
-    clear_err();
-    sequence_number++;
-  }
-
-  void debug_msg()
-  {
-    send_msg(9, str.str());
-    clear_err();
-    sequence_number++;
-  }
-
-  std::ostringstream str;
-
-  std::ostream &error()
-  {
-    return str;
-  }
-
-  // API stub, intentional noop
-  static inline std::ostream &eom(std::ostream &m)
-  {
-    return m;
-  }
-
-
-  bool get_error_found() const
-  {
-    return error_found;
-  }
-
-  void error_parse(unsigned level)
-  {
-    error_parse(level, str.str());
-    clear_err();
-  }
-
-  void clear_err()
-  {
-    str.clear();
-    str.str("");
-  }
-
-protected:
-  bool error_found;
-  source_locationt saved_error_location;
-  unsigned sequence_number;
-
-  void send_msg(unsigned level, const std::string &message)
-  {
-    if(message=="")
-      return;
-    if(level<=1)
-      error_found=true;
-
-    if(message_handler!=NULL)
-      message_handler->print(
-        level,
-        message,
-        sequence_number,
-        saved_error_location);
-
-    saved_error_location.make_nil();
-  }
-
-  void error_parse_line(
-    unsigned level,
-    const std::string &line);
-
-  void error_parse(
-    unsigned level,
-    const std::string &error);
-};
-
-#endif // CPROVER_UTIL_MESSAGE_STREAM_H
diff --git a/src/util/rename_symbol.cpp b/src/util/rename_symbol.cpp
index 55a9a7ff484..c6930a01d87 100644
--- a/src/util/rename_symbol.cpp
+++ b/src/util/rename_symbol.cpp
@@ -133,6 +133,9 @@ Function: rename_symbolt::have_to_rename
 
 bool rename_symbolt::have_to_rename(const exprt &dest) const
 {
+  if(expr_map.empty() && type_map.empty())
+    return false;
+
   // first look at type
 
   if(have_to_rename(dest.type()))
@@ -274,6 +277,9 @@ Function: rename_symbolt::have_to_rename
 
 bool rename_symbolt::have_to_rename(const typet &dest) const
 {
+  if(expr_map.empty() && type_map.empty())
+    return false;
+
   if(dest.has_subtype())
     if(have_to_rename(dest.subtype()))
       return true;
diff --git a/src/util/std_expr.cpp b/src/util/std_expr.cpp
index 5efc4d6e70c..4cb9eeff9cc 100644
--- a/src/util/std_expr.cpp
+++ b/src/util/std_expr.cpp
@@ -61,6 +61,16 @@ exprt disjunction(const exprt::operandst &op)
   }
 }
 
+void dynamic_object_exprt::set_instance(unsigned int instance)
+{
+  op0()=from_integer(instance, typet(ID_natural));
+}
+
+unsigned int dynamic_object_exprt::get_instance() const
+{
+  return std::stoul(id2string(to_constant_expr(op0()).get_value()));
+}
+
 /*******************************************************************\
 
 Function: conjunction
diff --git a/src/util/std_expr.h b/src/util/std_expr.h
index e3921c38d98..6c9ee03a69f 100644
--- a/src/util/std_expr.h
+++ b/src/util/std_expr.h
@@ -1505,15 +1505,9 @@ class dynamic_object_exprt:public exprt
     op1().id(ID_unknown);
   }
 
-  exprt &instance()
-  {
-    return op0();
-  }
+  void set_instance(unsigned int instance);
 
-  const exprt &instance() const
-  {
-    return op0();
-  }
+  unsigned int get_instance() const;
 
   exprt &valid()
   {
diff --git a/src/util/std_types.h b/src/util/std_types.h
index 11854535daf..02f4a3981a1 100644
--- a/src/util/std_types.h
+++ b/src/util/std_types.h
@@ -215,7 +215,7 @@ class struct_union_typet:public typet
       return set(ID_pretty_name, name);
     }
 
-    const bool get_anonymous() const
+    bool get_anonymous() const
     {
       return get_bool(ID_anonymous);
     }
@@ -225,7 +225,7 @@ class struct_union_typet:public typet
       return set(ID_anonymous, anonymous);
     }
 
-    const bool get_is_padding() const
+    bool get_is_padding() const
     {
       return get_bool(ID_C_is_padding);
     }
diff --git a/src/util/typecheck.cpp b/src/util/typecheck.cpp
index a305fa7ad4c..67b695e53fa 100644
--- a/src/util/typecheck.cpp
+++ b/src/util/typecheck.cpp
@@ -20,45 +20,6 @@ Author: Daniel Kroening, kroening@kroening.com
 
 \*******************************************************************/
 
-bool legacy_typecheckt::typecheck_main()
-{
-  try
-  {
-    typecheck();
-  }
-
-  catch(int)
-  {
-    error_msg();
-  }
-
-  catch(const char *e)
-  {
-    str << e;
-    error_msg();
-  }
-
-  catch(const std::string &e)
-  {
-    str << e;
-    error_msg();
-  }
-
-  return error_found;
-}
-
-/*******************************************************************\
-
-Function:
-
-  Inputs:
-
- Outputs:
-
- Purpose:
-
-\*******************************************************************/
-
 bool typecheckt::typecheck_main()
 {
   try
diff --git a/src/util/typecheck.h b/src/util/typecheck.h
index 7de4557de64..ee80f6e42f0 100644
--- a/src/util/typecheck.h
+++ b/src/util/typecheck.h
@@ -9,23 +9,8 @@ Author: Daniel Kroening, kroening@kroening.com
 #ifndef CPROVER_UTIL_TYPECHECK_H
 #define CPROVER_UTIL_TYPECHECK_H
 
-#include "message_stream.h"
-
-class legacy_typecheckt:public legacy_message_streamt
-{
-public:
-  explicit legacy_typecheckt(message_handlert &_message_handler):
-    legacy_message_streamt(_message_handler) { }
-  virtual ~legacy_typecheckt() { }
-
-protected:
-  // main function -- overload this one
-  virtual void typecheck()=0;
-
-public:
-  // call that one
-  virtual bool typecheck_main();
-};
+#include "expr.h"
+#include "message.h"
 
 class typecheckt:public messaget
 {
diff --git a/src/util/union_find.h b/src/util/union_find.h
index 5b2ff2504e4..2fee15e495b 100644
--- a/src/util/union_find.h
+++ b/src/util/union_find.h
@@ -157,7 +157,8 @@ class union_find:public numbering
   // are 'a' and 'b' in the same set?
   bool same_set(const T &a, const T &b) const
   {
-    typename subt::number_type na, nb;
+    typedef typename subt::number_type subt_number_typet;
+    subt_number_typet na=subt_number_typet(), nb=subt_number_typet();
     bool have_na=!subt::get_number(a, na),
          have_nb=!subt::get_number(b, nb);
 
diff --git a/src/xmllang/graphml.h b/src/xmllang/graphml.h
index 7a1050bcb00..1ef5aaedae1 100644
--- a/src/xmllang/graphml.h
+++ b/src/xmllang/graphml.h
@@ -49,7 +49,7 @@ class graphmlt:public grapht
     return false;
   }
 
-  const node_indext add_node_if_not_exists(std::string node_name)
+  node_indext add_node_if_not_exists(std::string node_name)
   {
     for(node_indext i=0; i