CBMC
ansi_c_language.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 "ansi_c_language.h"
10 
11 #include <util/config.h>
12 #include <util/get_base_name.h>
13 #include <util/symbol_table.h>
14 
15 #include <linking/linking.h>
17 
18 #include "ansi_c_entry_point.h"
20 #include "ansi_c_parser.h"
21 #include "ansi_c_typecheck.h"
22 #include "c_preprocess.h"
23 #include "expr2c.h"
24 #include "type2name.h"
25 
26 #include <fstream>
27 
28 std::set<std::string> ansi_c_languaget::extensions() const
29 {
30  return { "c", "i" };
31 }
32 
33 void ansi_c_languaget::modules_provided(std::set<std::string> &modules)
34 {
35  modules.insert(get_base_name(parse_path, true));
36 }
37 
40  std::istream &instream,
41  const std::string &path,
42  std::ostream &outstream,
43  message_handlert &message_handler)
44 {
45  // stdin?
46  if(path.empty())
47  return c_preprocess(instream, outstream, message_handler);
48 
49  return c_preprocess(path, outstream, message_handler);
50 }
51 
53  std::istream &instream,
54  const std::string &path,
55  message_handlert &message_handler)
56 {
57  // store the path
58  parse_path=path;
59 
60  // preprocessing
61  std::ostringstream o_preprocessed;
62 
63  if(preprocess(instream, path, o_preprocessed, message_handler))
64  return true;
65 
66  std::istringstream i_preprocessed(o_preprocessed.str());
67 
68  // parsing
69 
70  std::string code;
72  std::istringstream codestr(code);
73 
74  ansi_c_parsert ansi_c_parser{message_handler};
75  ansi_c_parser.set_file(ID_built_in);
76  ansi_c_parser.in=&codestr;
77  ansi_c_parser.for_has_scope=config.ansi_c.for_has_scope;
78  ansi_c_parser.ts_18661_3_Floatn_types=config.ansi_c.ts_18661_3_Floatn_types;
79  ansi_c_parser.float16_type = config.ansi_c.float16_type;
80  ansi_c_parser.bf16_type = config.ansi_c.bf16_type;
81  ansi_c_parser.cpp98=false; // it's not C++
82  ansi_c_parser.cpp11=false; // it's not C++
83  ansi_c_parser.mode=config.ansi_c.mode;
84 
85  ansi_c_scanner_init(ansi_c_parser);
86 
87  bool result=ansi_c_parser.parse();
88 
89  if(!result)
90  {
91  ansi_c_parser.set_line_no(0);
92  ansi_c_parser.set_file(path);
93  ansi_c_parser.in=&i_preprocessed;
94  ansi_c_scanner_init(ansi_c_parser);
95  result=ansi_c_parser.parse();
96  }
97 
98  // save result
99  parse_tree.swap(ansi_c_parser.parse_tree);
100 
101  return result;
102 }
103 
105  symbol_table_baset &symbol_table,
106  const std::string &module,
107  message_handlert &message_handler,
108  const bool keep_file_local)
109 {
110  return typecheck(symbol_table, module, message_handler, keep_file_local, {});
111 }
112 
114  symbol_table_baset &symbol_table,
115  const std::string &module,
116  message_handlert &message_handler,
117  const bool keep_file_local,
118  const std::set<irep_idt> &keep)
119 {
120  symbol_tablet new_symbol_table;
121 
122  if(ansi_c_typecheck(parse_tree, new_symbol_table, module, message_handler))
123  {
124  return true;
125  }
126 
128  new_symbol_table, message_handler, keep_file_local, keep);
129 
130  if(linking(symbol_table, new_symbol_table, message_handler))
131  return true;
132 
133  return false;
134 }
135 
137  symbol_table_baset &symbol_table,
138  message_handlert &message_handler)
139 {
140  // This creates __CPROVER_start and __CPROVER_initialize:
141  return ansi_c_entry_point(
142  symbol_table, message_handler, object_factory_params);
143 }
144 
146 {
147  parse_tree.output(out);
148 }
149 
150 std::unique_ptr<languaget> new_ansi_c_language()
151 {
152  return std::make_unique<ansi_c_languaget>();
153 }
154 
156  const exprt &expr,
157  std::string &code,
158  const namespacet &ns)
159 {
160  code=expr2c(expr, ns);
161  return false;
162 }
163 
165  const typet &type,
166  std::string &code,
167  const namespacet &ns)
168 {
169  code=type2c(type, ns);
170  return false;
171 }
172 
174  const typet &type,
175  std::string &name,
176  const namespacet &ns)
177 {
178  name=type2name(type, ns);
179  return false;
180 }
181 
183  const std::string &code,
184  const std::string &,
185  exprt &expr,
186  const namespacet &ns,
187  message_handlert &message_handler)
188 {
189  expr.make_nil();
190 
191  // no preprocessing yet...
192 
193  std::istringstream i_preprocessed(
194  "void __my_expression = (void) (\n"+code+"\n);");
195 
196  // parsing
197 
198  ansi_c_parsert ansi_c_parser{message_handler};
199  ansi_c_parser.set_file(irep_idt());
200  ansi_c_parser.in=&i_preprocessed;
201  ansi_c_parser.for_has_scope = config.ansi_c.for_has_scope;
202  ansi_c_parser.ts_18661_3_Floatn_types=config.ansi_c.ts_18661_3_Floatn_types;
203  ansi_c_parser.float16_type = config.ansi_c.float16_type;
204  ansi_c_parser.bf16_type = config.ansi_c.bf16_type;
205  ansi_c_parser.cpp98 = false; // it's not C++
206  ansi_c_parser.cpp11 = false; // it's not C++
207  ansi_c_parser.mode = config.ansi_c.mode;
208  ansi_c_scanner_init(ansi_c_parser);
209 
210  bool result=ansi_c_parser.parse();
211 
212  if(ansi_c_parser.parse_tree.items.empty())
213  result=true;
214  else
215  {
216  expr=ansi_c_parser.parse_tree.items.front().declarator().value();
217 
218  // typecheck it
219  result = ansi_c_typecheck(expr, message_handler, ns);
220  }
221 
222  // now remove that (void) cast
223  if(expr.id()==ID_typecast &&
224  expr.type().id()==ID_empty &&
225  expr.operands().size()==1)
226  {
227  expr = to_typecast_expr(expr).op();
228  }
229 
230  return result;
231 }
232 
234 {
235 }
bool ansi_c_entry_point(symbol_table_baset &symbol_table, message_handlert &message_handler, const c_object_factory_parameterst &object_factory_parameters)
void ansi_c_internal_additions(std::string &code, bool support_float16_type)
std::unique_ptr< languaget > new_ansi_c_language()
void ansi_c_scanner_init(ansi_c_parsert &)
bool ansi_c_typecheck(ansi_c_parse_treet &ansi_c_parse_tree, symbol_table_baset &symbol_table, const std::string &module, message_handlert &message_handler)
ANSI-C Language Type Checking.
configt config
Definition: config.cpp:25
bool c_preprocess(std::istream &instream, std::ostream &outstream, message_handlert &message_handler)
ANSI-C preprocessing.
~ansi_c_languaget() override
std::set< std::string > extensions() const override
void show_parse(std::ostream &out, message_handlert &) override
bool from_type(const typet &type, std::string &code, const namespacet &ns) override
Formats the given type in a language-specific way.
std::string parse_path
bool from_expr(const exprt &expr, std::string &code, const namespacet &ns) override
Formats the given expression in a language-specific way.
bool to_expr(const std::string &code, const std::string &module, exprt &expr, const namespacet &ns, message_handlert &message_handler) override
Parses the given string into an expression.
void modules_provided(std::set< std::string > &modules) override
bool type_to_name(const typet &type, std::string &name, const namespacet &ns) override
Encodes the given type in a language-specific way.
bool typecheck(symbol_table_baset &symbol_table, const std::string &module, message_handlert &message_handler, const bool keep_file_local) override
typecheck without removing specified entries from the symbol table
bool preprocess(std::istream &instream, const std::string &path, std::ostream &outstream, message_handlert &message_handler) override
ANSI-C preprocessing.
bool generate_support_functions(symbol_table_baset &symbol_table, message_handlert &message_handler) override
Create language-specific support functions, such as __CPROVER_start, __CPROVER_initialize and languag...
ansi_c_parse_treet parse_tree
c_object_factory_parameterst object_factory_params
bool parse(std::istream &instream, const std::string &path, message_handlert &message_handler) override
void swap(ansi_c_parse_treet &other)
void output(std::ostream &out) const
struct configt::ansi_ct ansi_c
Base class for all expressions.
Definition: expr.h:56
typet & type()
Return the type of the expression.
Definition: expr.h:84
operandst & operands()
Definition: expr.h:94
const irep_idt & id() const
Definition: irep.h:384
void make_nil()
Definition: irep.h:442
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
The symbol table base class interface.
The symbol table.
Definition: symbol_table.h:14
The type of an expression, extends irept.
Definition: type.h:29
const exprt & op() const
Definition: std_expr.h:391
std::string expr2c(const exprt &expr, const namespacet &ns, const expr2c_configurationt &configuration)
Definition: expr2c.cpp:4146
std::string type2c(const typet &type, const namespacet &ns, const expr2c_configurationt &configuration)
Definition: expr2c.cpp:4162
std::string get_base_name(const std::string &in, bool strip_suffix)
cleans a filename from path and extension
bool linking(symbol_table_baset &dest_symbol_table, const symbol_table_baset &new_symbol_table, message_handlert &message_handler)
Merges the symbol table new_symbol_table into dest_symbol_table, renaming symbols from new_symbol_tab...
Definition: linking.cpp:1618
ANSI-C Linking.
void remove_internal_symbols(symbol_table_baset &symbol_table, message_handlert &mh, const bool keep_file_local)
Removes internal symbols from a symbol table A symbol is EXPORTED if it is a.
Remove symbols that are internal only.
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2102
bool for_has_scope
Definition: config.h:151
bool float16_type
Definition: config.h:154
bool bf16_type
Definition: config.h:155
bool ts_18661_3_Floatn_types
Definition: config.h:152
flavourt mode
Definition: config.h:252
Author: Diffblue Ltd.
static std::string type2name(const typet &type, const namespacet &ns, symbol_numbert &symbol_number)
Definition: type2name.cpp:82
Type Naming for C.
dstringt irep_idt