CBMC
gcc_message_handler.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
9 #include "gcc_message_handler.h"
10 
11 #include <util/unicode.h>
12 
13 #include <fstream> // IWYU pragma: keep
14 #include <iostream>
15 
17  unsigned level,
18  const std::string &message,
19  const source_locationt &location)
20 {
21  message_handlert::print(level, message);
22 
23  if(verbosity >= level)
24  {
25  // gcc appears to send everything to cerr
26  auto &out = std::cerr;
27 
28  const irep_idt file = location.get_file();
29  const irep_idt line = location.get_line();
30  const irep_idt column = location.get_column();
31  const irep_idt function = location.get_function();
32 
33  if(!function.empty())
34  {
35  if(!file.empty())
36  out << string(messaget::bold) << file << ':' << string(messaget::reset)
37  << ' ';
38  out << "In function " << string(messaget::bold) << '\'' << function
39  << '\'' << string(messaget::reset) << ":\n";
40  }
41 
42  if(!line.empty())
43  {
44  out << string(messaget::bold);
45 
46  if(!file.empty())
47  out << file << ':';
48 
49  out << line << ':';
50 
51  if(column.empty())
52  out << "1: ";
53  else
54  out << column << ": ";
55 
56  if(
57  level == messaget::M_ERROR ||
59  {
60  out << string(messaget::red) << "error: ";
61  }
62  else if(level == messaget::M_WARNING)
63  out << string(messaget::bright_magenta) << "warning: ";
64 
65  out << string(messaget::reset);
66  }
67 
68  out << message << '\n';
69 
70  const auto file_name = location.full_path();
71  if(file_name.has_value() && !line.empty())
72  {
73  std::ifstream in(widen_if_needed(file_name.value()));
74 
75  if(in)
76  {
77  const auto line_number = std::stoull(id2string(line));
78  std::string source_line;
79  for(std::size_t l = 0; l < line_number; l++)
80  std::getline(in, source_line);
81 
82  if(in)
83  out << ' ' << source_line << '\n'; // gcc adds a space, clang doesn't
84  }
85  }
86 
87  out << std::flush;
88  }
89 }
90 
91 void gcc_message_handlert::print(unsigned level, const std::string &message)
92 {
93  message_handlert::print(level, message);
94 
95  // gcc appears to send everything to cerr
96  if(verbosity >= level)
97  std::cerr << message << '\n' << std::flush;
98 }
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
bool empty() const
Definition: dstring.h:89
std::string string(const messaget::commandt &c) const
feed a command into a string
void print(unsigned, const xmlt &) override
virtual void print(unsigned level, const std::string &message)=0
Definition: message.cpp:60
unsigned verbosity
Definition: message.h:72
static const commandt bright_magenta
render text with bright magenta foreground color
Definition: message.h:376
static const commandt reset
return to default formatting, as defined by the terminal
Definition: message.h:343
static const commandt bold
render text with bold font
Definition: message.h:382
@ M_ERROR
Definition: message.h:170
@ M_WARNING
Definition: message.h:170
static const commandt red
render text with red foreground color
Definition: message.h:346
const irep_idt & get_function() const
const irep_idt & get_column() const
const irep_idt & get_line() const
const irep_idt & get_file() const
std::optional< std::string > full_path() const
Get a path to the file, including working directory.
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
#define widen_if_needed(s)
Definition: unicode.h:28