|
19 | 19 | #include "expr_util.h"
|
20 | 20 | #include "fixedbv.h"
|
21 | 21 | #include "invariant.h"
|
| 22 | +#include "mathematical_expr.h" |
22 | 23 | #include "namespace.h"
|
23 | 24 | #include "pointer_offset_size.h"
|
24 | 25 | #include "rational.h"
|
25 | 26 | #include "rational_tools.h"
|
26 | 27 | #include "simplify_utils.h"
|
27 | 28 | #include "std_expr.h"
|
| 29 | +#include "string_expr.h" |
| 30 | +#include "symbol.h" |
28 | 31 | #include "type_eq.h"
|
29 | 32 |
|
30 | 33 | // #define DEBUGX
|
@@ -158,6 +161,77 @@ bool simplify_exprt::simplify_popcount(popcount_exprt &expr)
|
158 | 161 | return true;
|
159 | 162 | }
|
160 | 163 |
|
| 164 | +bool simplify_exprt::simplify_function_application(exprt &expr) |
| 165 | +{ |
| 166 | + const function_application_exprt &function_app = |
| 167 | + to_function_application_expr(expr); |
| 168 | + irep_idt func_id = |
| 169 | + function_app.function().find(ID_expression).get(ID_identifier); |
| 170 | + |
| 171 | + // Starts-with is used for .equals. |
| 172 | + if(func_id == ID_cprover_string_startswith_func) |
| 173 | + { |
| 174 | + // We want to get both arguments of any starts-with comparison, and |
| 175 | + // trace them back to the actual string instance. All variables on the |
| 176 | + // way must be constant for us to be sure this will work. |
| 177 | + auto &first_argument = to_string_expr(function_app.arguments().at(0)); |
| 178 | + auto &second_argument = to_string_expr(function_app.arguments().at(1)); |
| 179 | + |
| 180 | + if( |
| 181 | + first_argument.content().id() != ID_address_of || |
| 182 | + second_argument.content().id() != ID_address_of) |
| 183 | + { |
| 184 | + return true; |
| 185 | + } |
| 186 | + |
| 187 | + const address_of_exprt &first_address_of = |
| 188 | + to_address_of_expr(first_argument.content()); |
| 189 | + const address_of_exprt &second_address_of = |
| 190 | + to_address_of_expr(second_argument.content()); |
| 191 | + |
| 192 | + // Constants are got via address_of expressions, so this helps filter out |
| 193 | + // things that are non-constant. |
| 194 | + if( |
| 195 | + first_address_of.object().id() != ID_index || |
| 196 | + first_address_of.object().id() != ID_index) |
| 197 | + { |
| 198 | + return true; |
| 199 | + } |
| 200 | + |
| 201 | + const index_exprt &first_index_expression = |
| 202 | + to_index_expr(first_address_of.object()); |
| 203 | + const index_exprt &second_index_expression = |
| 204 | + to_index_expr(second_address_of.object()); |
| 205 | + |
| 206 | + const exprt &first_string_array = first_index_expression.array(); |
| 207 | + const exprt &second_string_array = second_index_expression.array(); |
| 208 | + |
| 209 | + // Check if our symbols type is an array. |
| 210 | + if( |
| 211 | + first_string_array.type().id() != ID_array || |
| 212 | + second_string_array.type().id() != ID_array) |
| 213 | + { |
| 214 | + return true; |
| 215 | + } |
| 216 | + |
| 217 | + // If so, it'll be a string array that we can use. |
| 218 | + const array_string_exprt &first_string = to_array_string_expr( |
| 219 | + ns.lookup(first_string_array.get(ID_identifier)).value); |
| 220 | + |
| 221 | + const array_string_exprt &second_string = to_array_string_expr( |
| 222 | + ns.lookup(second_string_array.get(ID_identifier)).value); |
| 223 | + |
| 224 | + // If the lengths are the same we can do the .equals substitute. |
| 225 | + if(first_string.length() == second_string.length()) |
| 226 | + { |
| 227 | + expr = from_integer(first_string == second_string ? 1 : 0, expr.type()); |
| 228 | + return false; |
| 229 | + } |
| 230 | + } |
| 231 | + |
| 232 | + return true; |
| 233 | +} |
| 234 | + |
161 | 235 | bool simplify_exprt::simplify_typecast(exprt &expr)
|
162 | 236 | {
|
163 | 237 | if(expr.operands().size()!=1)
|
@@ -2265,6 +2339,8 @@ bool simplify_exprt::simplify_node(exprt &expr)
|
2265 | 2339 | result=simplify_sign(expr) && result;
|
2266 | 2340 | else if(expr.id() == ID_popcount)
|
2267 | 2341 | result = simplify_popcount(to_popcount_expr(expr)) && result;
|
| 2342 | + else if(expr.id() == ID_function_application) |
| 2343 | + result = simplify_function_application(expr) && result; |
2268 | 2344 |
|
2269 | 2345 | #ifdef DEBUGX
|
2270 | 2346 | if(!result
|
|
0 commit comments