Skip to content

Commit 4125dbe

Browse files
author
Remi Delmas
committed
Implemented review requests
1 parent cb277b5 commit 4125dbe

File tree

1 file changed

+68
-59
lines changed

1 file changed

+68
-59
lines changed

src/analyses/goto_check.cpp

Lines changed: 68 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,6 @@ class goto_checkt
280280

281281
/// Maps a named-check name to the corresponding boolean flag.
282282
std::map<irep_idt, bool *> name_to_flag{
283-
{"no-enum-check", &no_enum_check},
284283
{"bounds-check", &enable_bounds_check},
285284
{"pointer-check", &enable_pointer_check},
286285
{"memory-leak-check", &enable_memory_leak_check},
@@ -308,11 +307,12 @@ class goto_checkt
308307

309308
/// \brief Adds "checked" pragmas for all currently active named checks
310309
/// 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;
312311

313312
/// \brief Adds "disable" pragmas for all named checks
314313
/// 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;
316316

317317
/// activation statuses for named checks
318318
typedef enum
@@ -323,7 +323,7 @@ class goto_checkt
323323
} check_statust;
324324

325325
/// 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>>;
327327

328328
/// Matches a named-check string of the form
329329
///
@@ -333,7 +333,7 @@ class goto_checkt
333333
///
334334
/// \returns a pair (name, status) if the match succeeds
335335
/// 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;
337337
};
338338

339339
void goto_checkt::collect_allocations(
@@ -1897,11 +1897,13 @@ optionalt<exprt> goto_checkt::rw_ok_check(exprt expr)
18971897
return {};
18981898
}
18991899

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.
19021904
///
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.
19051907
class flag_resett
19061908
{
19071909
public:
@@ -1913,16 +1915,18 @@ class flag_resett
19131915
/// \brief Store the current value of \p flag and
19141916
/// then set its value to \p new_value.
19151917
///
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
19181920
void set_flag(bool &flag, bool new_value, const irep_idt &flag_name)
19191921
{
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
19211927
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" +
19261930
instruction.source_location().pretty());
19271931
if(flag != new_value)
19281932
{
@@ -1931,17 +1935,28 @@ class flag_resett
19311935
}
19321936
}
19331937

1934-
/// \brief Sets the given flag to false, overriding any previous value.
1938+
/// Sets the given flag to false, overriding any previous value.
19351939
///
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)
19391943
{
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())
19421956
flags_to_reset[&flag] = flag;
1943-
flag = false;
1944-
}
1957+
1958+
// set the flag to false in all cases.
1959+
flag = false;
19451960
}
19461961

19471962
/// \brief Restore the values of all flags that have been
@@ -1955,6 +1970,7 @@ class flag_resett
19551970
private:
19561971
const goto_programt::instructiont &instruction;
19571972
std::map<bool *, bool> flags_to_reset;
1973+
std::set<bool *> disabled_flags;
19581974
};
19591975

19601976
void goto_checkt::goto_check(
@@ -1979,15 +1995,14 @@ void goto_checkt::goto_check(
19791995
goto_programt::instructiont &i=*it;
19801996

19811997
flag_resett resetter(i);
1982-
std::list<bool *> already_checked;
19831998
const auto &pragmas = i.source_location().get_pragmas();
19841999
for(const auto &d : pragmas)
19852000
{
19862001
// 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())
19892004
{
1990-
auto named_check = parsed.value();
2005+
auto named_check = matched.value();
19912006
auto name = named_check.first;
19922007
auto status = named_check.second;
19932008
bool *flag = name_to_flag.find(name)->second;
@@ -2000,16 +2015,12 @@ void goto_checkt::goto_check(
20002015
resetter.set_flag(*flag, false, name);
20012016
break;
20022017
case check_statust::CHECKED:
2003-
already_checked.push_back(flag);
2018+
resetter.disable_flag(*flag, name);
20042019
break;
20052020
}
20062021
}
20072022
}
20082023

2009-
// inhibit already checked checks
2010-
for(auto flag : already_checked)
2011-
resetter.disable(*flag);
2012-
20132024
// add checked pragmas for all active checks
20142025
add_active_named_check_pragmas(i.source_location_nonconst());
20152026

@@ -2494,46 +2505,44 @@ void goto_check(
24942505
}
24952506

24962507
void goto_checkt::add_active_named_check_pragmas(
2497-
source_locationt &source_location)
2508+
source_locationt &source_location) const
24982509
{
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));
25022513
}
25032514

25042515
void goto_checkt::add_all_disable_named_check_pragmas(
2505-
source_locationt &source_location)
2516+
source_locationt &source_location) const
25062517
{
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));
25092520
}
25102521

25112522
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
25132524
{
25142525
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"))
25182538
status = check_statust::ENABLE;
2519-
}
2520-
else if(s.find("disable:") == 0)
2521-
{
2539+
else if(!s.compare(0, 7, "disable"))
25222540
status = check_statust::DISABLE;
2523-
}
2524-
else if(s.find("checked:") == 0)
2525-
{
2541+
else if(!s.compare(0, 7, "checked"))
25262542
status = check_statust::CHECKED;
2527-
}
25282543
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
25372545

2546+
// success
25382547
return std::pair<irep_idt, check_statust>{name, status};
25392548
}

0 commit comments

Comments
 (0)