Skip to content

Commit 4682d07

Browse files
author
Thomas Kiley
authored
Merge pull request #5214 from thk123/thk/fix-property-sort
Fix property sort
2 parents 13bae95 + ac888bb commit 4682d07

File tree

4 files changed

+169
-53
lines changed

4 files changed

+169
-53
lines changed

src/goto-checker/report_util.cpp

Lines changed: 64 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -181,69 +181,80 @@ static void output_single_property_plain(
181181
<< messaget::eom;
182182
}
183183

184+
using propertyt = std::pair<irep_idt, property_infot>;
185+
/// Compare two properties according to the following sort:
186+
/// 1. alphabetical ordering of file name
187+
/// 2. alphabetical ordering of function name
188+
/// 3. numerical ordering of line number
189+
/// 4. alphabetical ordering of goal ID
190+
/// 5. number ordering of the goal ID number
191+
/// \param property1: The first property.
192+
/// \param property2: The second propery.
193+
/// \return True if the first property is less than the second property
194+
static bool
195+
is_property_less_than(const propertyt &property1, const propertyt &property2)
196+
{
197+
const auto &p1 = property1.second.pc->source_location;
198+
const auto &p2 = property2.second.pc->source_location;
199+
if(p1.get_file() != p2.get_file())
200+
return id2string(p1.get_file()) < id2string(p2.get_file());
201+
if(p1.get_function() != p2.get_function())
202+
return id2string(p1.get_function()) < id2string(p2.get_function());
203+
else if(
204+
!p1.get_line().empty() && !p2.get_line().empty() &&
205+
p1.get_line() != p2.get_line())
206+
return std::stoul(id2string(p1.get_line())) <
207+
std::stoul(id2string(p2.get_line()));
208+
209+
const auto split_property_id =
210+
[](const irep_idt &property_id) -> std::pair<std::string, std::size_t> {
211+
const auto property_string = id2string(property_id);
212+
const auto last_dot = property_string.rfind('.');
213+
std::string property_name;
214+
std::string property_number;
215+
if(last_dot == std::string::npos)
216+
{
217+
property_name = "";
218+
property_number = property_string;
219+
}
220+
else
221+
{
222+
property_name = property_string.substr(0, last_dot);
223+
property_number = property_string.substr(last_dot + 1);
224+
}
225+
const auto maybe_number = string2optional_size_t(property_number);
226+
if(maybe_number.has_value())
227+
return std::make_pair(property_name, *maybe_number);
228+
else
229+
return std::make_pair(property_name, 0);
230+
};
231+
232+
const auto left_split = split_property_id(property1.first);
233+
const auto left_id_name = left_split.first;
234+
const auto left_id_number = left_split.second;
235+
236+
const auto right_split = split_property_id(property2.first);
237+
const auto right_id_name = right_split.first;
238+
const auto right_id_number = right_split.second;
239+
240+
if(left_id_name != right_id_name)
241+
return left_id_name < right_id_name;
242+
else
243+
return left_id_number < right_id_number;
244+
}
245+
184246
static std::vector<propertiest::const_iterator>
185247
get_sorted_properties(const propertiest &properties)
186248
{
187249
std::vector<propertiest::const_iterator> sorted_properties;
188250
for(auto p_it = properties.begin(); p_it != properties.end(); p_it++)
189251
sorted_properties.push_back(p_it);
190-
// now determine an ordering for those goals:
191-
// 1. alphabetical ordering of file name
192-
// 2. alphabetical ordering of function name
193-
// 3. numerical ordering of line number
194-
// 4. alphabetical ordering of goal ID
195-
// 5. number ordering of the goal ID number
252+
196253
std::sort(
197254
sorted_properties.begin(),
198255
sorted_properties.end(),
199256
[](propertiest::const_iterator pit1, propertiest::const_iterator pit2) {
200-
const auto &p1 = pit1->second.pc->source_location;
201-
const auto &p2 = pit2->second.pc->source_location;
202-
if(p1.get_file() != p2.get_file())
203-
return id2string(p1.get_file()) < id2string(p2.get_file());
204-
if(p1.get_function() != p2.get_function())
205-
return id2string(p1.get_function()) < id2string(p2.get_function());
206-
else if(
207-
!p1.get_line().empty() && !p2.get_line().empty() &&
208-
p1.get_line() != p2.get_line())
209-
return std::stoul(id2string(p1.get_line())) <
210-
std::stoul(id2string(p2.get_line()));
211-
212-
const auto split_property_id =
213-
[](const irep_idt &property_id) -> std::pair<std::string, std::size_t> {
214-
const auto property_string = id2string(property_id);
215-
const auto last_dot = property_string.rfind('.');
216-
std::string property_name;
217-
std::string property_number;
218-
if(last_dot == std::string::npos)
219-
{
220-
property_name = "";
221-
property_number = property_string;
222-
}
223-
else
224-
{
225-
property_name = property_string.substr(0, last_dot);
226-
property_number = property_string.substr(last_dot + 1);
227-
}
228-
const auto maybe_number = string2optional_size_t(property_number);
229-
if(maybe_number.has_value())
230-
return std::make_pair(property_name, *maybe_number);
231-
else
232-
return std::make_pair(property_name, 0);
233-
};
234-
235-
const auto left_split = split_property_id(pit1->first);
236-
const auto left_id_name = left_split.first;
237-
const auto left_id_number = left_split.second;
238-
239-
const auto right_split = split_property_id(pit2->first);
240-
const auto right_id_name = left_split.first;
241-
const auto right_id_number = left_split.second;
242-
243-
if(left_id_name != right_id_name)
244-
return left_id_name < right_id_name;
245-
else
246-
return left_id_number < right_id_number;
257+
return is_property_less_than(*pit1, *pit2);
247258
});
248259
return sorted_properties;
249260
}

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ SRC += analyses/ai/ai.cpp \
1616
analyses/does_remove_const/is_type_at_least_as_const_as.cpp \
1717
big-int/big-int.cpp \
1818
compound_block_locations.cpp \
19+
goto-checker/report_util/is_property_less_than.cpp \
1920
goto-instrument/cover_instrument.cpp \
2021
goto-instrument/cover/cover_only.cpp \
2122
goto-programs/goto_model_function_type_consistency.cpp \
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright 2016-2020 Diffblue Limited. All Rights Reserved.
2+
3+
#include <goto-checker/report_util.cpp>
4+
#include <testing-utils/use_catch.h>
5+
6+
static goto_programt::instructiont instruction_for_location(
7+
const irep_idt &file,
8+
const irep_idt &function,
9+
size_t line_no)
10+
{
11+
source_locationt location;
12+
location.set_file(file);
13+
location.set_function(function);
14+
location.set_line(line_no);
15+
goto_programt::instructiont instruction;
16+
instruction.source_location = location;
17+
return instruction;
18+
}
19+
20+
static property_infot test_info(const goto_programt::const_targett &target)
21+
{
22+
return property_infot(target, "ignored", property_statust::UNKNOWN);
23+
}
24+
25+
static propertyt
26+
property(const irep_idt &identifier, const property_infot &info)
27+
{
28+
return std::make_pair(identifier, info);
29+
}
30+
31+
std::ostream &operator<<(std::ostream &os, const propertyt &value)
32+
{
33+
os << "{ property_id=" << value.first << ", "
34+
<< " property_location={ "
35+
<< " file=" << value.second.pc->source_location.get_file() << ", "
36+
<< " function=" << value.second.pc->source_location.get_function() << ", "
37+
<< " line=" << value.second.pc->source_location.get_line() << "}}";
38+
return os;
39+
}
40+
41+
TEST_CASE("Comparing two properties", "[core][goto-checker][report_util]")
42+
{
43+
SECTION("Compare locations")
44+
{
45+
goto_programt::instructionst instructions;
46+
instructions.push_back(instruction_for_location("fileA", "funcA", 1));
47+
instructions.push_back(instruction_for_location("fileA", "funcA", 2));
48+
instructions.push_back(instruction_for_location("fileA", "funcB", 1));
49+
instructions.push_back(instruction_for_location("fileA", "funcB", 2));
50+
instructions.push_back(instruction_for_location("fileB", "funcA", 1));
51+
instructions.push_back(instruction_for_location("fileB", "funcA", 2));
52+
instructions.push_back(instruction_for_location("fileB", "funcB", 1));
53+
instructions.push_back(instruction_for_location("fileB", "funcB", 2));
54+
55+
for(auto first_location = instructions.begin();
56+
first_location != instructions.end();
57+
++first_location)
58+
{
59+
for(auto second_location = std::next(first_location);
60+
second_location != instructions.end();
61+
++second_location)
62+
{
63+
const propertyt p1 = property("ignored", test_info(first_location));
64+
const propertyt p2 = property("ignored", test_info(second_location));
65+
INFO(p1);
66+
INFO(p2);
67+
REQUIRE(is_property_less_than(p1, p2));
68+
REQUIRE_FALSE(is_property_less_than(p2, p1));
69+
}
70+
}
71+
}
72+
SECTION("Compare property ids")
73+
{
74+
goto_programt::instructionst instructions;
75+
instructions.push_back(instruction_for_location("fileA", "funcA", 1));
76+
77+
std::vector<irep_idt> properties;
78+
properties.push_back("A.1");
79+
properties.push_back("A.2");
80+
properties.push_back("B.1");
81+
properties.push_back("B.2");
82+
83+
for(auto first_property = properties.begin();
84+
first_property != properties.end();
85+
++first_property)
86+
{
87+
for(auto second_property = std::next(first_property);
88+
second_property != properties.end();
89+
++second_property)
90+
{
91+
const propertyt p1 =
92+
property(*first_property, test_info(instructions.begin()));
93+
const propertyt p2 =
94+
property(*second_property, test_info(instructions.begin()));
95+
INFO(p1);
96+
INFO(p2);
97+
REQUIRE(is_property_less_than(p1, p2));
98+
REQUIRE_FALSE(is_property_less_than(p2, p1));
99+
}
100+
}
101+
}
102+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
goto-checker
2+
testing-utils

0 commit comments

Comments
 (0)