@@ -10,6 +10,7 @@ Author: Michael Tautschnig
1010
1111#include < util/expr_util.h>
1212#include < util/pointer_expr.h>
13+ #include < util/pointer_offset_size.h>
1314#include < util/simplify_expr.h>
1415#include < util/ssa_expr.h>
1516
@@ -193,6 +194,12 @@ simplify_expr_with_value_sett::simplify_inequality_pointer_object(
193194 to_object_descriptor_expr (value_set_element).root_object ());
194195 }
195196 }
197+ else if (
198+ pointer.is_constant () && to_constant_expr (pointer).is_null_pointer ())
199+ {
200+ objects.insert (
201+ exprt{ID_null_object, to_pointer_type (pointer.type ()).base_type ()});
202+ }
196203 return objects;
197204 };
198205
@@ -281,3 +288,99 @@ simplify_expr_with_value_sett::simplify_pointer_offset(
281288 return changed (
282289 simplify_rec (typecast_exprt::conditional_cast (*offset, expr.type ())));
283290}
291+
292+ simplify_exprt::resultt<> simplify_expr_with_value_sett::simplify_object_size (
293+ const object_size_exprt &expr)
294+ {
295+ const exprt &ptr = expr.pointer ();
296+
297+ if (ptr.type ().id () != ID_pointer)
298+ return unchanged (expr);
299+
300+ const ssa_exprt *ssa_symbol_expr = expr_try_dynamic_cast<ssa_exprt>(ptr);
301+
302+ if (!ssa_symbol_expr)
303+ return simplify_exprt::simplify_object_size (expr);
304+
305+ ssa_exprt l1_expr{*ssa_symbol_expr};
306+ l1_expr.remove_level_2 ();
307+ const std::vector<exprt> value_set_elements =
308+ value_set.get_value_set (l1_expr, ns);
309+
310+ std::optional<exprt> object_size;
311+
312+ for (const auto &value_set_element : value_set_elements)
313+ {
314+ if (
315+ value_set_element.id () == ID_unknown ||
316+ value_set_element.id () == ID_invalid ||
317+ is_failed_symbol (
318+ to_object_descriptor_expr (value_set_element).root_object ()) ||
319+ to_object_descriptor_expr (value_set_element).offset ().id () == ID_unknown)
320+ {
321+ object_size.reset ();
322+ break ;
323+ }
324+
325+ auto this_object_size_opt = size_of_expr (
326+ to_object_descriptor_expr (value_set_element).root_object ().type (), ns);
327+ if (
328+ !this_object_size_opt.has_value () ||
329+ (object_size.has_value () && *this_object_size_opt != *object_size))
330+ {
331+ object_size.reset ();
332+ break ;
333+ }
334+ else if (!object_size.has_value ())
335+ {
336+ object_size = this_object_size_opt;
337+ }
338+ }
339+
340+ if (!object_size.has_value ())
341+ return simplify_exprt::simplify_object_size (expr);
342+
343+ return changed (
344+ simplify_rec (typecast_exprt::conditional_cast (*object_size, expr.type ())));
345+ }
346+
347+ simplify_exprt::resultt<>
348+ simplify_expr_with_value_sett::simplify_is_invalid_pointer (
349+ const unary_exprt &expr)
350+ {
351+ const exprt &ptr = expr.op ();
352+
353+ if (ptr.type ().id () != ID_pointer)
354+ return unchanged (expr);
355+
356+ const ssa_exprt *ssa_symbol_expr = expr_try_dynamic_cast<ssa_exprt>(ptr);
357+
358+ if (!ssa_symbol_expr)
359+ return simplify_exprt::simplify_is_invalid_pointer (expr);
360+
361+ ssa_exprt l1_expr{*ssa_symbol_expr};
362+ l1_expr.remove_level_2 ();
363+ const std::vector<exprt> value_set_elements =
364+ value_set.get_value_set (l1_expr, ns);
365+
366+ bool all_valid = !value_set_elements.empty ();
367+
368+ for (const auto &value_set_element : value_set_elements)
369+ {
370+ if (
371+ value_set_element.id () == ID_unknown ||
372+ value_set_element.id () == ID_invalid ||
373+ is_failed_symbol (
374+ to_object_descriptor_expr (value_set_element).root_object ()) ||
375+ to_object_descriptor_expr (value_set_element).offset ().id () == ID_unknown)
376+ {
377+ all_valid = false ;
378+ break ;
379+ }
380+ }
381+
382+ if (all_valid)
383+ return changed (static_cast <exprt>(false_exprt{}));
384+ else
385+ return simplify_exprt::simplify_is_invalid_pointer (expr);
386+ }
0 commit comments