Skip to content

Commit 70269f5

Browse files
author
Daniel Kroening
committed
added show_on_source for abstract domains
The abstract states are shown in a different color on the source code text of the program, as opposed to the goto-program dump. Indentation of the output of the abstract is made to match the indentation of the source code.
1 parent 11ed46a commit 70269f5

File tree

4 files changed

+179
-3
lines changed

4 files changed

+179
-3
lines changed

src/goto-analyzer/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ SRC = goto_analyzer_main.cpp \
33
taint_analysis.cpp \
44
taint_parser.cpp \
55
unreachable_instructions.cpp \
6+
show_on_source.cpp \
67
static_show_domain.cpp \
78
static_simplifier.cpp \
89
static_verifier.cpp \

src/goto-analyzer/goto_analyzer_parse_options.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,12 @@ Author: Daniel Kroening, [email protected]
5757
#include <util/unicode.h>
5858
#include <util/version.h>
5959

60-
#include "taint_analysis.h"
61-
#include "unreachable_instructions.h"
60+
#include "show_on_source.h"
6261
#include "static_show_domain.h"
6362
#include "static_simplifier.h"
6463
#include "static_verifier.h"
64+
#include "taint_analysis.h"
65+
#include "unreachable_instructions.h"
6566

6667
goto_analyzer_parse_optionst::goto_analyzer_parse_optionst(
6768
int argc,
@@ -626,7 +627,18 @@ int goto_analyzer_parse_optionst::perform_analysis(const optionst &options)
626627

627628
if(options.get_bool_option("show"))
628629
{
629-
static_show_domain(goto_model, *analyzer, options, out);
630+
if(
631+
options.get_bool_option("json") || options.get_bool_option("xml") ||
632+
options.get_bool_option("dot") ||
633+
options.get_bool_option("dependence-graph"))
634+
{
635+
static_show_domain(goto_model, *analyzer, options, out);
636+
}
637+
else
638+
{
639+
show_on_source(goto_model, *analyzer, get_message_handler());
640+
}
641+
630642
return CPROVER_EXIT_SUCCESS;
631643
}
632644
else if(options.get_bool_option("verify"))

src/goto-analyzer/show_on_source.cpp

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*******************************************************************\
2+
3+
Module: goto-analyzer
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "show_on_source.h"
10+
11+
#include <util/file_util.h>
12+
#include <util/message.h>
13+
#include <util/unicode.h>
14+
15+
#include <analyses/ai.h>
16+
17+
#include <fstream>
18+
19+
/// get the source files with non-top abstract states
20+
static std::set<std::string>
21+
get_source_files(const goto_modelt &goto_model, const ai_baset &ai)
22+
{
23+
std::set<std::string> files;
24+
25+
for(const auto &f : goto_model.goto_functions.function_map)
26+
{
27+
forall_goto_program_instructions(i_it, f.second.body)
28+
{
29+
const auto abstract_state = ai.abstract_state_before(i_it);
30+
if(abstract_state->is_top())
31+
continue; // ignore
32+
33+
if(i_it->source_location.get_line().empty())
34+
continue; // ignore
35+
36+
auto f = i_it->source_location.full_path();
37+
38+
if(!f.empty())
39+
files.insert(f);
40+
}
41+
}
42+
43+
return files;
44+
}
45+
46+
/// print a string with indent to match given sample line
47+
static void print_with_indent(
48+
const std::string &src,
49+
const std::string &indent_line,
50+
std::ostream &out)
51+
{
52+
const std::size_t p = indent_line.find_first_not_of(" \t");
53+
const std::string indent =
54+
p == std::string::npos ? std::string("") : std::string(indent_line, 0, p);
55+
std::istringstream in(src);
56+
std::string src_line;
57+
while(std::getline(in, src_line))
58+
out << indent << src_line << '\n';
59+
}
60+
61+
/// output source code annotated with abstract states for given file
62+
void show_on_source(
63+
const std::string &source_file,
64+
const goto_modelt &goto_model,
65+
const ai_baset &ai,
66+
message_handlert &message_handler)
67+
{
68+
#ifdef _MSC_VER
69+
std::ifstream in(widen(source_file));
70+
#else
71+
std::ifstream in(source_file);
72+
#endif
73+
74+
messaget message(message_handler);
75+
76+
if(!in)
77+
{
78+
message.warning() << "Failed to open `" << source_file << "'"
79+
<< messaget::eom;
80+
return;
81+
}
82+
83+
std::map<std::size_t, ai_baset::locationt> line_map;
84+
85+
// Collect line numbers with non-top abstract states.
86+
// We pick the _first_ state for each line.
87+
for(const auto &f : goto_model.goto_functions.function_map)
88+
{
89+
forall_goto_program_instructions(i_it, f.second.body)
90+
{
91+
auto abstract_state = ai.abstract_state_before(i_it);
92+
if(abstract_state->is_top())
93+
continue; // ignore
94+
95+
const auto line = i_it->source_location.get_line();
96+
97+
if(line.empty())
98+
continue; // ignore
99+
100+
if(i_it->source_location.full_path() == source_file)
101+
{
102+
const std::size_t line_no = stoull(id2string(line));
103+
if(line_map.find(line_no) == line_map.end())
104+
line_map[line_no] = i_it;
105+
}
106+
}
107+
}
108+
109+
// now print file to message handler
110+
const namespacet ns(goto_model.symbol_table);
111+
112+
std::string line;
113+
for(std::size_t line_no = 1; std::getline(in, line); line_no++)
114+
{
115+
const auto map_it = line_map.find(line_no);
116+
if(map_it != line_map.end())
117+
{
118+
auto abstract_state = ai.abstract_state_before(map_it->second);
119+
std::ostringstream state_str;
120+
abstract_state->output(state_str, ai, ns);
121+
if(!state_str.str().empty())
122+
{
123+
message.result() << messaget::blue;
124+
print_with_indent(state_str.str(), line, message.result());
125+
message.result() << messaget::reset;
126+
}
127+
}
128+
129+
message.result() << line << messaget::eom;
130+
}
131+
}
132+
133+
/// output source code annotated with abstract states
134+
void show_on_source(
135+
const goto_modelt &goto_model,
136+
const ai_baset &ai,
137+
message_handlert &message_handler)
138+
{
139+
// first gather the source files that have something to show
140+
const auto source_files = get_source_files(goto_model, ai);
141+
142+
// now show file-by-file
143+
for(const auto &source_file : source_files)
144+
show_on_source(source_file, goto_model, ai, message_handler);
145+
}

src/goto-analyzer/show_on_source.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*******************************************************************\
2+
3+
Module: goto-analyzer
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_GOTO_ANALYZER_SHOW_ON_SOURCE_H
10+
#define CPROVER_GOTO_ANALYZER_SHOW_ON_SOURCE_H
11+
12+
class ai_baset;
13+
class goto_modelt;
14+
class message_handlert;
15+
16+
void show_on_source(const goto_modelt &, const ai_baset &, message_handlert &);
17+
18+
#endif // CPROVER_GOTO_ANALYZER_SHOW_ON_SOURCE_H

0 commit comments

Comments
 (0)