Skip to content

Commit 784be6f

Browse files
authored
Merge pull request #4946 from xbauch/fix/snapshot-source-location
Fix snapshot harness source location initialisation
2 parents fcc4904 + b222e57 commit 784be6f

File tree

6 files changed

+153
-10
lines changed

6 files changed

+153
-10
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <assert.h>
2+
3+
int global_var;
4+
5+
void initialize()
6+
{
7+
global_var = 1;
8+
}
9+
10+
void checkpoint()
11+
{
12+
}
13+
14+
int foo()
15+
{
16+
initialize();
17+
checkpoint();
18+
19+
assert(global_var == 0);
20+
//line to be used for init (20)
21+
assert(global_var == 0);
22+
23+
return 0;
24+
}
25+
26+
int main()
27+
{
28+
foo();
29+
30+
return 0;
31+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
main.c
3+
global_var --harness-type initialise-with-memory-snapshot --initial-source-location main.c:20
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[foo.assertion.1\] line [0-9]+ assertion global_var == 0: SUCCESS$
7+
^\[foo.assertion.2\] line [0-9]+ assertion global_var == 0: FAILURE$
8+
VERIFICATION FAILED
9+
--
10+
^warning: ignoring
11+
--
12+
The first assertion is succeeding because unreachable.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <assert.h>
2+
3+
struct S
4+
{
5+
int c1;
6+
int c2;
7+
} st;
8+
9+
int *p;
10+
11+
void initialize()
12+
{
13+
st.c1 = 1;
14+
st.c2 = 3;
15+
p = &(st.c2);
16+
}
17+
18+
void checkpoint()
19+
{
20+
}
21+
22+
int foo()
23+
{
24+
initialize();
25+
checkpoint();
26+
27+
assert(st.c1 + 2 == st.c2);
28+
assert(st.c1 + 2 == *p);
29+
assert(*p == st.c2);
30+
*p = st.c2 + 1;
31+
assert(*p == st.c2);
32+
33+
return 0;
34+
}
35+
36+
int main()
37+
{
38+
foo();
39+
40+
return 0;
41+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
main.c
3+
st,p --harness-type initialise-with-memory-snapshot --initial-source-location main.c:27
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
\[foo.assertion.1\] line [0-9]+ assertion st.c1 \+ 2 == st.c2: SUCCESS
7+
\[foo.assertion.2\] line [0-9]+ assertion st.c1 \+ 2 == \*p: SUCCESS
8+
\[foo.assertion.3\] line [0-9]+ assertion \*p == st.c2: SUCCESS
9+
\[foo.assertion.4\] line [0-9]+ assertion \*p == st.c2: SUCCESS
10+
VERIFICATION SUCCESSFUL
11+
--
12+
^warning: ignoring

src/goto-harness/memory_snapshot_harness_generator.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -504,22 +504,30 @@ memory_snapshot_harness_generatort::initialize_entry_via_source(
504504
{
505505
PRECONDITION(!entry_source_location.file_name.empty());
506506

507+
source_location_matcht best_match;
507508
// by line: iterate over all instructions until source location match
508509
for(const auto &entry : goto_functions.function_map)
509510
{
510511
const auto &goto_function = entry.second;
511512
// if !body_available() then body.instruction.empty() and that's fine
512513
const auto &goto_program = goto_function.body;
513514

514-
const auto corresponding_instruction =
515+
const auto candidate_instruction =
515516
entry_source_location.find_first_corresponding_instruction(
516517
goto_program.instructions);
517518

518-
if(corresponding_instruction != goto_program.instructions.end())
519-
return entry_locationt{entry.first, corresponding_instruction};
519+
if(candidate_instruction.first != goto_program.instructions.end())
520+
{
521+
best_match.match_up(
522+
candidate_instruction.second, entry.first, candidate_instruction.first);
523+
}
520524
}
521-
throw invalid_command_line_argument_exceptiont(
522-
"could not find the specified entry point", "--initial-source-location");
525+
526+
if(best_match.match_found)
527+
return entry_locationt{best_match.function_name, best_match.instruction};
528+
else
529+
throw invalid_command_line_argument_exceptiont(
530+
"could not find the specified entry point", "--initial-source-location");
523531
}
524532

525533
goto_programt::const_targett memory_snapshot_harness_generatort::
@@ -537,16 +545,24 @@ goto_programt::const_targett memory_snapshot_harness_generatort::
537545
});
538546
}
539547

540-
goto_programt::const_targett memory_snapshot_harness_generatort::
541-
entry_source_locationt::find_first_corresponding_instruction(
548+
std::pair<goto_programt::const_targett, size_t>
549+
memory_snapshot_harness_generatort::entry_source_locationt::
550+
find_first_corresponding_instruction(
542551
const goto_programt::instructionst &instructions) const
543552
{
544-
return std::find_if(
553+
auto it = std::find_if(
545554
instructions.begin(),
546555
instructions.end(),
547556
[this](const goto_programt::instructiont &instruction) {
548557
return instruction.source_location.get_file() == file_name &&
549558
safe_string2unsigned(id2string(
550559
instruction.source_location.get_line())) >= line_number;
551560
});
561+
562+
if(it == instructions.end())
563+
return {it, 0};
564+
else
565+
return {it,
566+
safe_string2unsigned(id2string(it->source_location.get_line())) -
567+
line_number};
552568
}

src/goto-harness/memory_snapshot_harness_generator.h

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,10 @@ class memory_snapshot_harness_generatort : public goto_harness_generatort
9797
/// Returns the first \ref goto_programt::instructiont represented by this
9898
/// source location, i.e. one with the same file name and line number
9999
/// \param instructions: list of instructions to be searched
100-
/// \return iterator to the right instruction (or `end()`)
101-
goto_programt::const_targett find_first_corresponding_instruction(
100+
/// \return <iterator to the right instruction (or `end()`), distance to
101+
/// `line_number`>
102+
std::pair<goto_programt::const_targett, size_t>
103+
find_first_corresponding_instruction(
102104
const goto_programt::instructionst &instructions) const;
103105
};
104106

@@ -124,6 +126,35 @@ class memory_snapshot_harness_generatort : public goto_harness_generatort
124126
}
125127
};
126128

129+
/// Wraps the information for source location match candidates. Keeps track of
130+
/// the distance between user specified source code line and goto-program
131+
/// instruction line.
132+
struct source_location_matcht
133+
{
134+
size_t distance;
135+
irep_idt function_name;
136+
goto_programt::const_targett instruction;
137+
bool match_found;
138+
139+
source_location_matcht() : distance(0), match_found(false)
140+
{
141+
}
142+
143+
void match_up(
144+
const size_t &candidate_distance,
145+
const irep_idt &candidate_function_name,
146+
const goto_programt::const_targett &candidate_instruction)
147+
{
148+
if(match_found && distance <= candidate_distance)
149+
return;
150+
151+
match_found = true;
152+
distance = candidate_distance;
153+
function_name = candidate_function_name;
154+
instruction = candidate_instruction;
155+
}
156+
};
157+
127158
/// Find and return the entry instruction (requested by the user as goto
128159
/// location: function name + location number)
129160
/// \param entry_goto_location: user specified goto location

0 commit comments

Comments
 (0)