24
24
#include < algorithm>
25
25
#include < functional>
26
26
#include < numeric>
27
+ #include < stack>
27
28
28
29
// / Post order visitation is used in order to construct the the smt terms bottom
29
30
// / upwards without using recursion to traverse the input `exprt`. Therefore
@@ -1845,6 +1846,46 @@ exprt lower_address_of_array_index(exprt expr)
1845
1846
return expr;
1846
1847
}
1847
1848
1849
+ // / Post order traversal where the children of a node are only visited if
1850
+ // / applying the \p filter function to that node returns true. Note that this
1851
+ // / function is based on the `visit_post_template` function.
1852
+ void filtered_visit_post (
1853
+ const exprt &_expr,
1854
+ std::function<bool (const exprt &)> filter,
1855
+ std::function<void(const exprt &)> visitor)
1856
+ {
1857
+ struct stack_entryt
1858
+ {
1859
+ const exprt *e;
1860
+ bool operands_pushed;
1861
+ explicit stack_entryt (const exprt *_e) : e(_e), operands_pushed(false )
1862
+ {
1863
+ }
1864
+ };
1865
+
1866
+ std::stack<stack_entryt> stack;
1867
+
1868
+ stack.emplace (&_expr);
1869
+
1870
+ while (!stack.empty ())
1871
+ {
1872
+ auto &top = stack.top ();
1873
+ if (top.operands_pushed )
1874
+ {
1875
+ visitor (*top.e );
1876
+ stack.pop ();
1877
+ }
1878
+ else
1879
+ {
1880
+ // do modification of 'top' before pushing in case 'top' isn't stable
1881
+ top.operands_pushed = true ;
1882
+ if (filter (*top.e ))
1883
+ for (auto &op : top.e ->operands ())
1884
+ stack.emplace (&op);
1885
+ }
1886
+ }
1887
+ }
1888
+
1848
1889
smt_termt convert_expr_to_smt (
1849
1890
const exprt &expr,
1850
1891
const smt_object_mapt &object_map,
@@ -1864,18 +1905,30 @@ smt_termt convert_expr_to_smt(
1864
1905
#endif
1865
1906
sub_expression_mapt sub_expression_map;
1866
1907
const auto lowered_expr = lower_address_of_array_index (expr);
1867
- lowered_expr.visit_post ([&](const exprt &expr) {
1868
- const auto find_result = sub_expression_map.find (expr);
1869
- if (find_result != sub_expression_map.cend ())
1870
- return ;
1871
- smt_termt term = dispatch_expr_to_smt_conversion (
1872
- expr,
1873
- sub_expression_map,
1874
- object_map,
1875
- pointer_sizes,
1876
- object_size,
1877
- is_dynamic_object);
1878
- sub_expression_map.emplace_hint (find_result, expr, std::move (term));
1879
- });
1908
+ filtered_visit_post (
1909
+ lowered_expr,
1910
+ [](const exprt &expr) {
1911
+ // Code values inside "address of" expressions do not need to be converted
1912
+ // as the "address of" conversion only depends on the object identifier.
1913
+ // Avoiding the conversion side steps a need to convert arbitrary code to
1914
+ // SMT terms.
1915
+ const auto address_of = expr_try_dynamic_cast<address_of_exprt>(expr);
1916
+ if (!address_of)
1917
+ return true ;
1918
+ return !can_cast_type<code_typet>(address_of->object ().type ());
1919
+ },
1920
+ [&](const exprt &expr) {
1921
+ const auto find_result = sub_expression_map.find (expr);
1922
+ if (find_result != sub_expression_map.cend ())
1923
+ return ;
1924
+ smt_termt term = dispatch_expr_to_smt_conversion (
1925
+ expr,
1926
+ sub_expression_map,
1927
+ object_map,
1928
+ pointer_sizes,
1929
+ object_size,
1930
+ is_dynamic_object);
1931
+ sub_expression_map.emplace_hint (find_result, expr, std::move (term));
1932
+ });
1880
1933
return std::move (sub_expression_map.at (lowered_expr));
1881
1934
}
0 commit comments