@@ -280,7 +280,6 @@ class goto_checkt
280
280
281
281
// / Maps a named-check name to the corresponding boolean flag.
282
282
std::map<irep_idt, bool *> name_to_flag{
283
- {" no-enum-check" , &no_enum_check},
284
283
{" bounds-check" , &enable_bounds_check},
285
284
{" pointer-check" , &enable_pointer_check},
286
285
{" memory-leak-check" , &enable_memory_leak_check},
@@ -308,11 +307,12 @@ class goto_checkt
308
307
309
308
// / \brief Adds "checked" pragmas for all currently active named checks
310
309
// / on the given source location.
311
- void add_active_named_check_pragmas (source_locationt &source_location);
310
+ void add_active_named_check_pragmas (source_locationt &source_location) const ;
312
311
313
312
// / \brief Adds "disable" pragmas for all named checks
314
313
// / on the given source location.
315
- void add_all_disable_named_check_pragmas (source_locationt &source_location);
314
+ void
315
+ add_all_disable_named_check_pragmas (source_locationt &source_location) const ;
316
316
317
317
// / activation statuses for named checks
318
318
typedef enum
@@ -323,7 +323,7 @@ class goto_checkt
323
323
} check_statust;
324
324
325
325
// / optional (named-check, status) pair
326
- typedef optionalt<std::pair<irep_idt, check_statust>> named_check_statust ;
326
+ using named_check_statust = optionalt<std::pair<irep_idt, check_statust>>;
327
327
328
328
// / Matches a named-check string of the form
329
329
// /
@@ -333,7 +333,7 @@ class goto_checkt
333
333
// /
334
334
// / \returns a pair (name, status) if the match succeeds
335
335
// / and the name is known, nothing otherwise.
336
- named_check_statust match_named_check (irep_idt named_check);
336
+ named_check_statust match_named_check (const irep_idt & named_check) const ;
337
337
};
338
338
339
339
void goto_checkt::collect_allocations (
@@ -1897,11 +1897,13 @@ optionalt<exprt> goto_checkt::rw_ok_check(exprt expr)
1897
1897
return {};
1898
1898
}
1899
1899
1900
- // / \brief Set a Boolean flag to a new value (via `set_flag`) and restore
1901
- // / the previous value when the entire object goes out of scope.
1900
+ // / Allows to:
1901
+ // / - override a Boolean flag with a new value via `set_flag`
1902
+ // / - set a Boolean flag to false via `disable_flag`, such that
1903
+ // / previous `set_flag` are overridden and future `set_flag` are ignored.
1902
1904
// /
1903
- // / \remarks Calls to set_value are tracked to allow detecting doubles sets
1904
- // / with different values and trigger an INVARIANT .
1905
+ // / A flag's initial value (before any `set_flag` or `disable_flag`) is restored
1906
+ // / when the entire object goes out of scope .
1905
1907
class flag_resett
1906
1908
{
1907
1909
public:
@@ -1913,16 +1915,18 @@ class flag_resett
1913
1915
// / \brief Store the current value of \p flag and
1914
1916
// / then set its value to \p new_value.
1915
1917
// /
1916
- // / \remarks an INVARIANT triggers iff the flag is set
1917
- // / more than once with different values.
1918
+ // / - calling `set_flag` after `disable_flag` is a no-op
1919
+ // / - calling `set_flag` twice triggers an INVARIANT
1918
1920
void set_flag (bool &flag, bool new_value, const irep_idt &flag_name)
1919
1921
{
1920
- bool seen = flags_to_reset.find (&flag) != flags_to_reset.end ();
1922
+ // make this a no-op if the flag is disabled
1923
+ if (disabled_flags.find (&flag) != disabled_flags.end ())
1924
+ return ;
1925
+
1926
+ // detect double sets
1921
1927
INVARIANT (
1922
- !(seen && flag != new_value),
1923
- " Flag " + id2string (flag_name) +
1924
- " set twice with incompatible values "
1925
- " at \n " +
1928
+ flags_to_reset.find (&flag) == flags_to_reset.end (),
1929
+ " Flag " + id2string (flag_name) + " set twice at \n " +
1926
1930
instruction.source_location ().pretty ());
1927
1931
if (flag != new_value)
1928
1932
{
@@ -1931,17 +1935,28 @@ class flag_resett
1931
1935
}
1932
1936
}
1933
1937
1934
- // / \brief Sets the given flag to false, overriding any previous value.
1938
+ // / Sets the given flag to false, overriding any previous value.
1935
1939
// /
1936
- // / Contrary to \ref set_flag, does not trigger an INVARIANT
1937
- // / if the flag was already seen before.
1938
- void disable (bool &flag)
1940
+ // / - calling `disable_flag` after ` set_flag` overrides the set value
1941
+ // / - calling `disable_flag` twice triggers an INVARIANT
1942
+ void disable_flag (bool &flag, const irep_idt &flag_name )
1939
1943
{
1940
- if (flag)
1941
- {
1944
+ INVARIANT (
1945
+ disabled_flags.find (&flag) == disabled_flags.end (),
1946
+ " Flag " + id2string (flag_name) + " disabled twice at \n " +
1947
+ instruction.source_location ().pretty ());
1948
+
1949
+ disabled_flags.insert (&flag);
1950
+
1951
+ // If the flag has not already been set,
1952
+ // we store its current value in the reset map.
1953
+ // Otherwise, the reset map already holds
1954
+ // the initial value we want to reset it to, keep it as is.
1955
+ if (flags_to_reset.find (&flag) == flags_to_reset.end ())
1942
1956
flags_to_reset[&flag] = flag;
1943
- flag = false ;
1944
- }
1957
+
1958
+ // set the flag to false in all cases.
1959
+ flag = false ;
1945
1960
}
1946
1961
1947
1962
// / \brief Restore the values of all flags that have been
@@ -1955,6 +1970,7 @@ class flag_resett
1955
1970
private:
1956
1971
const goto_programt::instructiont &instruction;
1957
1972
std::map<bool *, bool > flags_to_reset;
1973
+ std::set<bool *> disabled_flags;
1958
1974
};
1959
1975
1960
1976
void goto_checkt::goto_check (
@@ -1979,15 +1995,14 @@ void goto_checkt::goto_check(
1979
1995
goto_programt::instructiont &i=*it;
1980
1996
1981
1997
flag_resett resetter (i);
1982
- std::list<bool *> already_checked;
1983
1998
const auto &pragmas = i.source_location ().get_pragmas ();
1984
1999
for (const auto &d : pragmas)
1985
2000
{
1986
2001
// match named-check related pragmas
1987
- auto parsed = match_named_check (d.first );
1988
- if (parsed .has_value ())
2002
+ auto matched = match_named_check (d.first );
2003
+ if (matched .has_value ())
1989
2004
{
1990
- auto named_check = parsed .value ();
2005
+ auto named_check = matched .value ();
1991
2006
auto name = named_check.first ;
1992
2007
auto status = named_check.second ;
1993
2008
bool *flag = name_to_flag.find (name)->second ;
@@ -2000,16 +2015,12 @@ void goto_checkt::goto_check(
2000
2015
resetter.set_flag (*flag, false , name);
2001
2016
break ;
2002
2017
case check_statust::CHECKED:
2003
- already_checked. push_back ( flag);
2018
+ resetter. disable_flag (* flag, name );
2004
2019
break ;
2005
2020
}
2006
2021
}
2007
2022
}
2008
2023
2009
- // inhibit already checked checks
2010
- for (auto flag : already_checked)
2011
- resetter.disable (*flag);
2012
-
2013
2024
// add checked pragmas for all active checks
2014
2025
add_active_named_check_pragmas (i.source_location_nonconst ());
2015
2026
@@ -2494,46 +2505,44 @@ void goto_check(
2494
2505
}
2495
2506
2496
2507
void goto_checkt::add_active_named_check_pragmas (
2497
- source_locationt &source_location)
2508
+ source_locationt &source_location) const
2498
2509
{
2499
- for (auto it : name_to_flag)
2500
- if (*(it .second ))
2501
- source_location.add_pragma (" checked:" + id2string (it .first ));
2510
+ for (const auto &entry : name_to_flag)
2511
+ if (*(entry .second ))
2512
+ source_location.add_pragma (" checked:" + id2string (entry .first ));
2502
2513
}
2503
2514
2504
2515
void goto_checkt::add_all_disable_named_check_pragmas (
2505
- source_locationt &source_location)
2516
+ source_locationt &source_location) const
2506
2517
{
2507
- for (auto it : name_to_flag)
2508
- source_location.add_pragma (" disable:" + id2string (it .first ));
2518
+ for (const auto &entry : name_to_flag)
2519
+ source_location.add_pragma (" disable:" + id2string (entry .first ));
2509
2520
}
2510
2521
2511
2522
goto_checkt::named_check_statust
2512
- goto_checkt::match_named_check (irep_idt named_check)
2523
+ goto_checkt::match_named_check (const irep_idt & named_check) const
2513
2524
{
2514
2525
auto s = id2string (named_check);
2515
- auto status = check_statust::DISABLE;
2516
- if (s.find (" enable:" ) == 0 )
2517
- {
2526
+ auto col = s.find (" :" );
2527
+
2528
+ if (col == std::string::npos)
2529
+ return {}; // separator not found
2530
+
2531
+ auto name = s.substr (col + 1 );
2532
+
2533
+ if (name_to_flag.find (name) == name_to_flag.end ())
2534
+ return {}; // name unknown
2535
+
2536
+ check_statust status;
2537
+ if (!s.compare (0 , 6 , " enable" ))
2518
2538
status = check_statust::ENABLE;
2519
- }
2520
- else if (s.find (" disable:" ) == 0 )
2521
- {
2539
+ else if (!s.compare (0 , 7 , " disable" ))
2522
2540
status = check_statust::DISABLE;
2523
- }
2524
- else if (s.find (" checked:" ) == 0 )
2525
- {
2541
+ else if (!s.compare (0 , 7 , " checked" ))
2526
2542
status = check_statust::CHECKED;
2527
- }
2528
2543
else
2529
- {
2530
- return {};
2531
- }
2532
-
2533
- auto sep = s.find (" :" );
2534
- auto name = s.substr (sep + 1 );
2535
- if (name_to_flag.find (name) == name_to_flag.end ())
2536
- return {};
2544
+ return {}; // prefix unknow
2537
2545
2546
+ // success
2538
2547
return std::pair<irep_idt, check_statust>{name, status};
2539
2548
}
0 commit comments