@@ -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,14 @@ 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 (const exprt &expr, const guardt &guard, bool is_assigned )
541
543
{
542
544
if (!enable_enum_range_check)
543
545
return ;
544
546
547
+ if (is_assigned)
548
+ return ; // not in range yet
549
+
545
550
// we might be looking at a lowered enum_is_in_range_exprt, skip over these
546
551
const auto &pragmas = expr.source_location ().get_pragmas ();
547
552
for (const auto &d : pragmas)
@@ -1807,13 +1812,13 @@ void goto_check_ct::check_rec_address(const exprt &expr, const guardt &guard)
1807
1812
1808
1813
if (expr.id () == ID_dereference)
1809
1814
{
1810
- check_rec (to_dereference_expr (expr).pointer (), guard);
1815
+ check_rec (to_dereference_expr (expr).pointer (), guard, false );
1811
1816
}
1812
1817
else if (expr.id () == ID_index)
1813
1818
{
1814
1819
const index_exprt &index_expr = to_index_expr (expr);
1815
1820
check_rec_address (index_expr.array (), guard);
1816
- check_rec (index_expr.index (), guard);
1821
+ check_rec (index_expr.index (), guard, false );
1817
1822
}
1818
1823
else
1819
1824
{
@@ -1843,7 +1848,7 @@ void goto_check_ct::check_rec_logical_op(const exprt &expr, const guardt &guard)
1843
1848
return guard (implication (conjunction (constraints), expr));
1844
1849
};
1845
1850
1846
- check_rec (op, new_guard);
1851
+ check_rec (op, new_guard, false );
1847
1852
1848
1853
constraints.push_back (expr.id () == ID_or ? boolean_negate (op) : op);
1849
1854
}
@@ -1855,20 +1860,20 @@ void goto_check_ct::check_rec_if(const if_exprt &if_expr, const guardt &guard)
1855
1860
if_expr.cond ().is_boolean (),
1856
1861
" first argument of if must be boolean, but got " + if_expr.cond ().pretty ());
1857
1862
1858
- check_rec (if_expr.cond (), guard);
1863
+ check_rec (if_expr.cond (), guard, false );
1859
1864
1860
1865
{
1861
1866
auto new_guard = [&guard, &if_expr](exprt expr) {
1862
1867
return guard (implication (if_expr.cond (), std::move (expr)));
1863
1868
};
1864
- check_rec (if_expr.true_case (), new_guard);
1869
+ check_rec (if_expr.true_case (), new_guard, false );
1865
1870
}
1866
1871
1867
1872
{
1868
1873
auto new_guard = [&guard, &if_expr](exprt expr) {
1869
1874
return guard (implication (not_exprt (if_expr.cond ()), std::move (expr)));
1870
1875
};
1871
- check_rec (if_expr.false_case (), new_guard);
1876
+ check_rec (if_expr.false_case (), new_guard, false );
1872
1877
}
1873
1878
}
1874
1879
@@ -1878,7 +1883,7 @@ bool goto_check_ct::check_rec_member(
1878
1883
{
1879
1884
const dereference_exprt &deref = to_dereference_expr (member.struct_op ());
1880
1885
1881
- check_rec (deref.pointer (), guard);
1886
+ check_rec (deref.pointer (), guard, false );
1882
1887
1883
1888
// avoid building the following expressions when pointer_validity_check
1884
1889
// would return immediately anyway
@@ -1969,7 +1974,10 @@ void goto_check_ct::check_rec_arithmetic_op(
1969
1974
}
1970
1975
}
1971
1976
1972
- void goto_check_ct::check_rec (const exprt &expr, const guardt &guard)
1977
+ void goto_check_ct::check_rec (
1978
+ const exprt &expr,
1979
+ const guardt &guard,
1980
+ bool is_assigned)
1973
1981
{
1974
1982
if (expr.id () == ID_exists || expr.id () == ID_forall)
1975
1983
{
@@ -1980,7 +1988,7 @@ void goto_check_ct::check_rec(const exprt &expr, const guardt &guard)
1980
1988
return guard (forall_exprt (quantifier_expr.symbol (), expr));
1981
1989
};
1982
1990
1983
- check_rec (quantifier_expr.where (), new_guard);
1991
+ check_rec (quantifier_expr.where (), new_guard, false );
1984
1992
return ;
1985
1993
}
1986
1994
else if (expr.id () == ID_address_of)
@@ -2007,10 +2015,10 @@ void goto_check_ct::check_rec(const exprt &expr, const guardt &guard)
2007
2015
}
2008
2016
2009
2017
for (const auto &op : expr.operands ())
2010
- check_rec (op, guard);
2018
+ check_rec (op, guard, false );
2011
2019
2012
2020
if (expr.type ().id () == ID_c_enum_tag)
2013
- enum_range_check (expr, guard);
2021
+ enum_range_check (expr, guard, is_assigned );
2014
2022
2015
2023
if (expr.id () == ID_index)
2016
2024
{
@@ -2059,9 +2067,9 @@ void goto_check_ct::check_rec(const exprt &expr, const guardt &guard)
2059
2067
}
2060
2068
}
2061
2069
2062
- void goto_check_ct::check (const exprt &expr)
2070
+ void goto_check_ct::check (const exprt &expr, bool is_assigned )
2063
2071
{
2064
- check_rec (expr, identity);
2072
+ check_rec (expr, identity, is_assigned );
2065
2073
}
2066
2074
2067
2075
void goto_check_ct::memory_leak_check (const irep_idt &function_id)
@@ -2151,7 +2159,7 @@ void goto_check_ct::goto_check(
2151
2159
2152
2160
if (i.has_condition ())
2153
2161
{
2154
- check (i.condition ());
2162
+ check (i.condition (), false );
2155
2163
}
2156
2164
2157
2165
// magic ERROR label?
@@ -2184,45 +2192,32 @@ void goto_check_ct::goto_check(
2184
2192
2185
2193
if (statement == ID_expression)
2186
2194
{
2187
- check (code);
2195
+ check (code, false );
2188
2196
}
2189
2197
else if (statement == ID_printf)
2190
2198
{
2191
2199
for (const auto &op : code.operands ())
2192
- check (op);
2200
+ check (op, false );
2193
2201
}
2194
2202
}
2195
2203
else if (i.is_assign ())
2196
2204
{
2197
2205
const exprt &assign_lhs = i.assign_lhs ();
2198
2206
const exprt &assign_rhs = i.assign_rhs ();
2199
2207
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);
2208
+ check (assign_lhs, true );
2209
+ check (assign_rhs, false );
2209
2210
2210
2211
// the LHS might invalidate any assertion
2211
2212
invalidate (assign_lhs);
2212
2213
}
2213
2214
else if (i.is_function_call ())
2214
2215
{
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 ());
2216
+ check (i.call_lhs (), true );
2217
+ check (i.call_function (), false );
2223
2218
2224
2219
for (const auto &arg : i.call_arguments ())
2225
- check (arg);
2220
+ check (arg, false );
2226
2221
2227
2222
check_shadow_memory_api_calls (i);
2228
2223
@@ -2231,7 +2226,7 @@ void goto_check_ct::goto_check(
2231
2226
}
2232
2227
else if (i.is_set_return_value ())
2233
2228
{
2234
- check (i.return_value ());
2229
+ check (i.return_value (), false );
2235
2230
// the return value invalidate any assertion
2236
2231
invalidate (i.return_value ());
2237
2232
}
@@ -2342,7 +2337,7 @@ void goto_check_ct::check_shadow_memory_api_calls(
2342
2337
{
2343
2338
const exprt &expr = i.call_arguments ()[0 ];
2344
2339
PRECONDITION (expr.type ().id () == ID_pointer);
2345
- check (dereference_exprt (expr));
2340
+ check (dereference_exprt (expr), false );
2346
2341
}
2347
2342
}
2348
2343
0 commit comments