Skip to content

Commit dc7afc7

Browse files
author
kroening
committed
type_to_name: canonic type names, language independent
git-svn-id: svn+ssh://svn.cprover.org/srv/svn/cbmc/trunk@6388 6afb6bc1-c8e4-404c-8f48-9ae832c5b171
1 parent 4c671f1 commit dc7afc7

10 files changed

+315
-41
lines changed

src/ansi-c/ansi_c_language.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Author: Daniel Kroening, [email protected]
2525
#include "trans_unit.h"
2626
#include "c_preprocess.h"
2727
#include "ansi_c_internal_additions.h"
28+
#include "type2name.h"
2829

2930
/*******************************************************************\
3031
@@ -306,6 +307,27 @@ bool ansi_c_languaget::from_type(
306307

307308
/*******************************************************************\
308309
310+
Function: ansi_c_languaget::type_to_name
311+
312+
Inputs:
313+
314+
Outputs:
315+
316+
Purpose:
317+
318+
\*******************************************************************/
319+
320+
bool ansi_c_languaget::type_to_name(
321+
const typet &type,
322+
std::string &name,
323+
const namespacet &ns)
324+
{
325+
name=type2name(type, ns);
326+
return false;
327+
}
328+
329+
/*******************************************************************\
330+
309331
Function: ansi_c_languaget::to_expr
310332
311333
Inputs:

src/ansi-c/ansi_c_language.h

+5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ class ansi_c_languaget:public languaget
5252
std::string &code,
5353
const namespacet &ns);
5454

55+
virtual bool type_to_name(
56+
const typet &type,
57+
std::string &name,
58+
const namespacet &ns);
59+
5560
virtual bool to_expr(
5661
const std::string &code,
5762
const std::string &module,

src/ansi-c/type2name.cpp

+163-16
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,88 @@ Author: Daniel Kroening, [email protected]
99
#include <util/i2string.h>
1010
#include <util/std_types.h>
1111
#include <util/arith_tools.h>
12+
#include <util/namespace.h>
13+
#include <util/symbol.h>
14+
#include <util/symbol_table.h>
1215

1316
#include "type2name.h"
1417

18+
typedef hash_map_cont<irep_idt, std::pair<size_t, bool>, irep_id_hash>
19+
symbol_numbert;
20+
21+
static std::string type2name(
22+
const typet &type,
23+
const namespacet &ns,
24+
symbol_numbert &symbol_number);
25+
26+
/*******************************************************************\
27+
28+
Function: type2name_symbol
29+
30+
Inputs:
31+
32+
Outputs:
33+
34+
Purpose:
35+
36+
\*******************************************************************/
37+
38+
static std::string type2name_symbol(
39+
const typet &type,
40+
const namespacet &ns,
41+
symbol_numbert &symbol_number)
42+
{
43+
const irep_idt &identifier=type.get(ID_identifier);
44+
45+
const symbolt *symbol;
46+
47+
if(ns.lookup(identifier, symbol))
48+
return "SYM#"+id2string(identifier)+"#";
49+
50+
assert(symbol && symbol->is_type);
51+
52+
if(symbol->type.id()!=ID_struct &&
53+
symbol->type.id()!=ID_union)
54+
return type2name(symbol->type, ns, symbol_number);
55+
56+
std::string result;
57+
58+
// assign each symbol a number when seen for the first time
59+
std::pair<symbol_numbert::iterator, bool> entry=
60+
symbol_number.insert(std::make_pair(
61+
identifier,
62+
std::make_pair(symbol_number.size(), true)));
63+
64+
// new entry, add definition
65+
if(entry.second)
66+
{
67+
result="SYM#"+i2string(entry.first->second.first);
68+
result+="={";
69+
result+=type2name(symbol->type, ns, symbol_number);
70+
result+='}';
71+
72+
entry.first->second.second=false;
73+
}
74+
#if 0
75+
// in recursion, print the shorthand only
76+
else if(entry.first->second.second)
77+
result="SYM#"+i2string(entry.first->second.first);
78+
// entering recursion
79+
else
80+
{
81+
entry.first->second.second=true;
82+
result=type2name(symbol->type, ns, symbol_number);
83+
entry.first->second.second=false;
84+
}
85+
#else
86+
// shorthand only as structs/unions are always symbols
87+
else
88+
result="SYM#"+i2string(entry.first->second.first);
89+
#endif
90+
91+
return result;
92+
}
93+
1594
/*******************************************************************\
1695
1796
Function: type2name
@@ -24,7 +103,11 @@ Function: type2name
24103
25104
\*******************************************************************/
26105

27-
std::string type2name(const typet &type)
106+
static bool parent_is_sym_check=false;
107+
static std::string type2name(
108+
const typet &type,
109+
const namespacet &ns,
110+
symbol_numbert &symbol_number)
28111
{
29112
std::string result;
30113

@@ -38,6 +121,14 @@ std::string type2name(const typet &type)
38121
if(type.get_bool(ID_C_volatile))
39122
result+='v';
40123

124+
if(type.get_bool(ID_C_transparent_union))
125+
result+='t';
126+
127+
// this isn't really a qualifier, but the linker needs to
128+
// distinguish these - should likely be fixed in the linker instead
129+
if(!type.source_location().get_function().empty())
130+
result+='l';
131+
41132
if(type.id()==irep_idt())
42133
throw "Empty type encountered.";
43134
else if(type.id()==ID_empty)
@@ -69,15 +160,15 @@ std::string type2name(const typet &type)
69160
{
70161
const code_typet &t=to_code_type(type);
71162
const code_typet::parameterst parameters=t.parameters();
72-
result+="P(";
163+
result+=type2name(t.return_type(), ns, symbol_number)+"(";
73164

74165
for(code_typet::parameterst::const_iterator
75166
it=parameters.begin();
76167
it!=parameters.end();
77168
it++)
78169
{
79170
if(it!=parameters.begin()) result+='|';
80-
result+=type2name(it->type());
171+
result+=type2name(it->type(), ns, symbol_number);
81172
}
82173

83174
if(t.has_ellipsis())
@@ -87,24 +178,32 @@ std::string type2name(const typet &type)
87178
}
88179

89180
result+=")->";
90-
result+=type2name(t.return_type());
181+
result+=type2name(t.return_type(), ns, symbol_number);
91182
}
92183
else if(type.id()==ID_array)
93184
{
94185
const array_typet &t=to_array_type(type);
95186
mp_integer size;
96187
if(to_integer(t.size(), size))
97188
result+="ARR?";
189+
else if(t.size().id()==ID_symbol)
190+
result+="ARR"+t.size().get_string(ID_identifier);
98191
else
99192
result+="ARR"+integer2string(size);
100193
}
101-
else if(type.id()==ID_symbol)
194+
else if(type.id()==ID_symbol ||
195+
type.id()==ID_c_enum_tag ||
196+
type.id()==ID_struct_tag ||
197+
type.id()==ID_union_tag)
102198
{
103-
result+="SYM#"+type.get_string(ID_identifier)+"#";
199+
parent_is_sym_check=true;
200+
result+=type2name_symbol(type, ns, symbol_number);
104201
}
105202
else if(type.id()==ID_struct ||
106203
type.id()==ID_union)
107204
{
205+
assert(parent_is_sym_check);
206+
parent_is_sym_check=false;
108207
if(type.id()==ID_struct) result+="ST";
109208
if(type.id()==ID_union) result+="UN";
110209
const struct_union_typet &t=to_struct_union_type(type);
@@ -116,19 +215,31 @@ std::string type2name(const typet &type)
116215
it++)
117216
{
118217
if(it!=components.begin()) result+='|';
119-
result+=type2name(it->type());
120-
result+="'"+it->get_string(ID_name)+"'|";
218+
result+=type2name(it->type(), ns, symbol_number);
219+
result+="'"+it->get_string(ID_name)+"'";
121220
}
122221
result+=']';
123222
}
124223
else if(type.id()==ID_incomplete_struct)
125224
result +="ST?";
126225
else if(type.id()==ID_incomplete_union)
127226
result +="UN?";
128-
else if(type.id()==ID_c_enum_tag)
129-
result +="EN"+to_c_enum_tag_type(type).get_string(ID_identifier)+"#";
130227
else if(type.id()==ID_c_enum)
131-
result +="EN"+type.get_string(ID_width);
228+
{
229+
result +="EN";
230+
const c_enum_typet &t=to_c_enum_type(type);
231+
const c_enum_typet::memberst &members=t.members();
232+
result+='[';
233+
for(c_enum_typet::memberst::const_iterator
234+
it=members.begin();
235+
it!=members.end();
236+
++it)
237+
{
238+
if(it!=members.begin()) result+='|';
239+
result+=id2string(it->get_value());
240+
result+="'"+id2string(it->get_identifier())+"'";
241+
}
242+
}
132243
else if(type.id()==ID_incomplete_c_enum)
133244
result +="EN?";
134245
else if(type.id()==ID_c_bit_field)
@@ -143,7 +254,7 @@ std::string type2name(const typet &type)
143254
if(type.has_subtype())
144255
{
145256
result+='{';
146-
result+=type2name(type.subtype());
257+
result+=type2name(type.subtype(), ns, symbol_number);
147258
result+='}';
148259
}
149260

@@ -152,13 +263,49 @@ std::string type2name(const typet &type)
152263
result+='$';
153264
forall_subtypes(it, type)
154265
{
155-
result+=type2name(*it);
156-
result+="|";
266+
result+=type2name(*it, ns, symbol_number);
267+
result+='|';
157268
}
158-
result.resize(result.size()-1);
159-
result+='$';
269+
result[result.size()-1]='$';
160270
}
161271

162272
return result;
163273
}
164274

275+
/*******************************************************************\
276+
277+
Function: type2name
278+
279+
Inputs:
280+
281+
Outputs:
282+
283+
Purpose:
284+
285+
\*******************************************************************/
286+
287+
std::string type2name(const typet &type, const namespacet &ns)
288+
{
289+
parent_is_sym_check=true;
290+
symbol_numbert symbol_number;
291+
return type2name(type, ns, symbol_number);
292+
}
293+
294+
/*******************************************************************\
295+
296+
Function: type2name
297+
298+
Inputs:
299+
300+
Outputs:
301+
302+
Purpose:
303+
304+
\*******************************************************************/
305+
306+
std::string type2name(const typet &type)
307+
{
308+
symbol_tablet symbol_table;
309+
return type2name(type, namespacet(symbol_table));
310+
}
311+

src/ansi-c/type2name.h

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ Author: Daniel Kroening, [email protected]
1111
#include <util/type.h>
1212

1313
std::string type2name(const typet &type);
14+
std::string type2name(const typet &type, const namespacet &ns);

src/cpp/cpp_language.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Author: Daniel Kroening, [email protected]
2424
#include "expr2cpp.h"
2525
#include "cpp_parser.h"
2626
#include "cpp_typecheck.h"
27+
#include "cpp_type2name.h"
2728

2829
/*******************************************************************\
2930
@@ -383,6 +384,27 @@ bool cpp_languaget::from_type(
383384

384385
/*******************************************************************\
385386
387+
Function: cpp_languaget::type_to_name
388+
389+
Inputs:
390+
391+
Outputs:
392+
393+
Purpose:
394+
395+
\*******************************************************************/
396+
397+
bool cpp_languaget::type_to_name(
398+
const typet &type,
399+
std::string &name,
400+
const namespacet &ns)
401+
{
402+
name=cpp_type2name(type);
403+
return false;
404+
}
405+
406+
/*******************************************************************\
407+
386408
Function: cpp_languaget::to_expr
387409
388410
Inputs:

src/cpp/cpp_language.h

+5
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ class cpp_languaget:public languaget
6161
std::string &code,
6262
const namespacet &ns);
6363

64+
virtual bool type_to_name(
65+
const typet &type,
66+
std::string &name,
67+
const namespacet &ns);
68+
6469
// conversion from string into expression
6570
virtual bool to_expr(
6671
const std::string &code,

0 commit comments

Comments
 (0)