@@ -157,11 +157,13 @@ class goto_check_ct
157
157
// / guard.
158
158
// / \param expr: the expression to be checked
159
159
// / \param guard: the condition for when the check should be made
160
- void check_rec (const exprt &expr, const guardt &guard);
160
+ // / \param is_assigned: the expression is assigned to
161
+ void check_rec (const exprt &expr, const guardt &guard, bool is_assigned);
161
162
162
163
// / Initiate the recursively analysis of \p expr with its `guard' set to TRUE.
163
164
// / \param expr: the expression to be checked
164
- void check (const exprt &expr);
165
+ // / \param is_assigned: the expression is assigned to
166
+ void check (const exprt &expr, bool is_assigned);
165
167
166
168
struct conditiont
167
169
{
@@ -183,7 +185,7 @@ class goto_check_ct
183
185
void float_div_by_zero_check (const div_exprt &, const guardt &);
184
186
void mod_by_zero_check (const mod_exprt &, const guardt &);
185
187
void mod_overflow_check (const mod_exprt &, const guardt &);
186
- void enum_range_check (const exprt &, const guardt &);
188
+ void enum_range_check (const exprt &, const guardt &, bool is_assigned );
187
189
void undefined_shift_check (const shift_exprt &, const guardt &);
188
190
void pointer_rel_check (const binary_exprt &, const guardt &);
189
191
void pointer_overflow_check (const exprt &, const guardt &);
@@ -537,11 +539,17 @@ void goto_check_ct::float_div_by_zero_check(
537
539
guard);
538
540
}
539
541
540
- void goto_check_ct::enum_range_check (const exprt &expr, const guardt &guard)
542
+ void goto_check_ct::enum_range_check (
543
+ const exprt &expr,
544
+ const guardt &guard,
545
+ bool is_assigned)
541
546
{
542
547
if (!enable_enum_range_check)
543
548
return ;
544
549
550
+ if (is_assigned)
551
+ return ; // not in range yet
552
+
545
553
// we might be looking at a lowered enum_is_in_range_exprt, skip over these
546
554
const auto &pragmas = expr.source_location ().get_pragmas ();
547
555
for (const auto &d : pragmas)
@@ -1807,13 +1815,13 @@ void goto_check_ct::check_rec_address(const exprt &expr, const guardt &guard)
1807
1815
1808
1816
if (expr.id () == ID_dereference)
1809
1817
{
1810
- check_rec (to_dereference_expr (expr).pointer (), guard);
1818
+ check_rec (to_dereference_expr (expr).pointer (), guard, false );
1811
1819
}
1812
1820
else if (expr.id () == ID_index)
1813
1821
{
1814
1822
const index_exprt &index_expr = to_index_expr (expr);
1815
1823
check_rec_address (index_expr.array (), guard);
1816
- check_rec (index_expr.index (), guard);
1824
+ check_rec (index_expr.index (), guard, false );
1817
1825
}
1818
1826
else
1819
1827
{
@@ -1843,7 +1851,7 @@ void goto_check_ct::check_rec_logical_op(const exprt &expr, const guardt &guard)
1843
1851
return guard (implication (conjunction (constraints), expr));
1844
1852
};
1845
1853
1846
- check_rec (op, new_guard);
1854
+ check_rec (op, new_guard, false );
1847
1855
1848
1856
constraints.push_back (expr.id () == ID_or ? boolean_negate (op) : op);
1849
1857
}
@@ -1855,20 +1863,20 @@ void goto_check_ct::check_rec_if(const if_exprt &if_expr, const guardt &guard)
1855
1863
if_expr.cond ().is_boolean (),
1856
1864
" first argument of if must be boolean, but got " + if_expr.cond ().pretty ());
1857
1865
1858
- check_rec (if_expr.cond (), guard);
1866
+ check_rec (if_expr.cond (), guard, false );
1859
1867
1860
1868
{
1861
1869
auto new_guard = [&guard, &if_expr](exprt expr) {
1862
1870
return guard (implication (if_expr.cond (), std::move (expr)));
1863
1871
};
1864
- check_rec (if_expr.true_case (), new_guard);
1872
+ check_rec (if_expr.true_case (), new_guard, false );
1865
1873
}
1866
1874
1867
1875
{
1868
1876
auto new_guard = [&guard, &if_expr](exprt expr) {
1869
1877
return guard (implication (not_exprt (if_expr.cond ()), std::move (expr)));
1870
1878
};
1871
- check_rec (if_expr.false_case (), new_guard);
1879
+ check_rec (if_expr.false_case (), new_guard, false );
1872
1880
}
1873
1881
}
1874
1882
@@ -1878,7 +1886,7 @@ bool goto_check_ct::check_rec_member(
1878
1886
{
1879
1887
const dereference_exprt &deref = to_dereference_expr (member.struct_op ());
1880
1888
1881
- check_rec (deref.pointer (), guard);
1889
+ check_rec (deref.pointer (), guard, false );
1882
1890
1883
1891
// avoid building the following expressions when pointer_validity_check
1884
1892
// would return immediately anyway
@@ -1969,7 +1977,10 @@ void goto_check_ct::check_rec_arithmetic_op(
1969
1977
}
1970
1978
}
1971
1979
1972
- void goto_check_ct::check_rec (const exprt &expr, const guardt &guard)
1980
+ void goto_check_ct::check_rec (
1981
+ const exprt &expr,
1982
+ const guardt &guard,
1983
+ bool is_assigned)
1973
1984
{
1974
1985
if (expr.id () == ID_exists || expr.id () == ID_forall)
1975
1986
{
@@ -1980,7 +1991,7 @@ void goto_check_ct::check_rec(const exprt &expr, const guardt &guard)
1980
1991
return guard (forall_exprt (quantifier_expr.symbol (), expr));
1981
1992
};
1982
1993
1983
- check_rec (quantifier_expr.where (), new_guard);
1994
+ check_rec (quantifier_expr.where (), new_guard, false );
1984
1995
return ;
1985
1996
}
1986
1997
else if (expr.id () == ID_address_of)
@@ -2007,10 +2018,10 @@ void goto_check_ct::check_rec(const exprt &expr, const guardt &guard)
2007
2018
}
2008
2019
2009
2020
for (const auto &op : expr.operands ())
2010
- check_rec (op, guard);
2021
+ check_rec (op, guard, false );
2011
2022
2012
2023
if (expr.type ().id () == ID_c_enum_tag)
2013
- enum_range_check (expr, guard);
2024
+ enum_range_check (expr, guard, is_assigned );
2014
2025
2015
2026
if (expr.id () == ID_index)
2016
2027
{
@@ -2059,9 +2070,9 @@ void goto_check_ct::check_rec(const exprt &expr, const guardt &guard)
2059
2070
}
2060
2071
}
2061
2072
2062
- void goto_check_ct::check (const exprt &expr)
2073
+ void goto_check_ct::check (const exprt &expr, bool is_assigned )
2063
2074
{
2064
- check_rec (expr, identity);
2075
+ check_rec (expr, identity, is_assigned );
2065
2076
}
2066
2077
2067
2078
void goto_check_ct::memory_leak_check (const irep_idt &function_id)
@@ -2151,7 +2162,7 @@ void goto_check_ct::goto_check(
2151
2162
2152
2163
if (i.has_condition ())
2153
2164
{
2154
- check (i.condition ());
2165
+ check (i.condition (), false );
2155
2166
}
2156
2167
2157
2168
// magic ERROR label?
@@ -2184,45 +2195,32 @@ void goto_check_ct::goto_check(
2184
2195
2185
2196
if (statement == ID_expression)
2186
2197
{
2187
- check (code);
2198
+ check (code, false );
2188
2199
}
2189
2200
else if (statement == ID_printf)
2190
2201
{
2191
2202
for (const auto &op : code.operands ())
2192
- check (op);
2203
+ check (op, false );
2193
2204
}
2194
2205
}
2195
2206
else if (i.is_assign ())
2196
2207
{
2197
2208
const exprt &assign_lhs = i.assign_lhs ();
2198
2209
const exprt &assign_rhs = i.assign_rhs ();
2199
2210
2200
- // Disable enum range checks for left-hand sides as their values are yet
2201
- // to be set (by this assignment).
2202
- {
2203
- flag_overridet resetter (i.source_location ());
2204
- resetter.disable_flag (enable_enum_range_check, " enum_range_check" );
2205
- check (assign_lhs);
2206
- }
2207
-
2208
- check (assign_rhs);
2211
+ check (assign_lhs, true );
2212
+ check (assign_rhs, false );
2209
2213
2210
2214
// the LHS might invalidate any assertion
2211
2215
invalidate (assign_lhs);
2212
2216
}
2213
2217
else if (i.is_function_call ())
2214
2218
{
2215
- // Disable enum range checks for left-hand sides as their values are yet
2216
- // to be set (by this function call).
2217
- {
2218
- flag_overridet resetter (i.source_location ());
2219
- resetter.disable_flag (enable_enum_range_check, " enum_range_check" );
2220
- check (i.call_lhs ());
2221
- }
2222
- check (i.call_function ());
2219
+ check (i.call_lhs (), true );
2220
+ check (i.call_function (), false );
2223
2221
2224
2222
for (const auto &arg : i.call_arguments ())
2225
- check (arg);
2223
+ check (arg, false );
2226
2224
2227
2225
check_shadow_memory_api_calls (i);
2228
2226
@@ -2231,7 +2229,7 @@ void goto_check_ct::goto_check(
2231
2229
}
2232
2230
else if (i.is_set_return_value ())
2233
2231
{
2234
- check (i.return_value ());
2232
+ check (i.return_value (), false );
2235
2233
// the return value invalidate any assertion
2236
2234
invalidate (i.return_value ());
2237
2235
}
@@ -2342,7 +2340,7 @@ void goto_check_ct::check_shadow_memory_api_calls(
2342
2340
{
2343
2341
const exprt &expr = i.call_arguments ()[0 ];
2344
2342
PRECONDITION (expr.type ().id () == ID_pointer);
2345
- check (dereference_exprt (expr));
2343
+ check (dereference_exprt (expr), false );
2346
2344
}
2347
2345
}
2348
2346
0 commit comments