cprover
convert_integer_literal.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: C++ Language Conversion
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
13 
14 #include <cassert>
15 #include <cctype>
16 
17 #include <util/arith_tools.h>
18 #include <util/config.h>
19 #include <util/std_types.h>
20 #include <util/std_expr.h>
21 #include <util/string2int.h>
22 
23 exprt convert_integer_literal(const std::string &src)
24 {
25  bool is_unsigned=false, is_imaginary=false;
26  unsigned long_cnt=0;
27  unsigned width_suffix=0;
28  unsigned base=10;
29 
30  for(unsigned i=0; i<src.size(); i++)
31  {
32  char ch=src[i];
33 
34  if(ch=='u' || ch=='U')
35  is_unsigned=true;
36  else if(ch=='l' || ch=='L')
37  long_cnt++;
38  else if(ch=='i' || ch=='I')
39  {
40  // This can be "1i128" in MS mode,
41  // and "10i" (imaginary) for GCC.
42  // If it's followed by a number, we do MS mode.
43  if((i+1)<src.size() && isdigit(src[i+1]))
44  width_suffix=unsafe_string2unsigned(src.substr(i+1));
45  else
46  is_imaginary=true;
47  }
48  else if(ch=='j' || ch=='J')
49  is_imaginary=true;
50  }
51 
52  mp_integer value;
53 
54  if(src.size()>=2 && src[0]=='0' && tolower(src[1])=='x')
55  {
56  // hex; strip "0x"
57  base=16;
58  std::string without_prefix(src, 2, std::string::npos);
59  value=string2integer(without_prefix, 16);
60  }
61  else if(src.size()>=2 && src[0]=='0' && tolower(src[1])=='b')
62  {
63  // binary; strip "0x"
64  // see http://gcc.gnu.org/onlinedocs/gcc/Binary-constants.html
65  base=2;
66  std::string without_prefix(src, 2, std::string::npos);
67  value=string2integer(without_prefix, 2);
68  }
69  else if(src.size()>=2 && src[0]=='0' && isdigit(src[1]))
70  {
71  // octal
72  base=8;
73  value=string2integer(src, 8);
74  }
75  else
76  {
77  // The default is base 10.
78  value=string2integer(src, 10);
79  }
80 
81  if(width_suffix!=0)
82  {
83  // this is a Microsoft extension
84  irep_idt c_type;
85 
86  if(width_suffix<=config.ansi_c.int_width)
87  c_type=is_unsigned?ID_unsigned_int:ID_signed_int;
88  else if(width_suffix<=config.ansi_c.long_int_width)
89  c_type=is_unsigned?ID_unsigned_long_int:ID_signed_long_int;
90  else
91  c_type=is_unsigned?ID_unsigned_long_long_int:ID_signed_long_long_int;
92 
93  bitvector_typet type(
94  is_unsigned ? ID_unsignedbv : ID_signedbv, width_suffix);
95  type.set(ID_C_c_type, c_type);
96 
97  exprt result=from_integer(value, type);
98 
99  return result;
100  }
101 
102  mp_integer value_abs=value;
103 
104  if(value<0)
105  value_abs.negate();
106 
107  bool is_hex_or_oct_or_bin=(base==8) || (base==16) || (base==2);
108 
109  #define FITS(width, signed) \
110  ((signed?!is_unsigned:(is_unsigned || is_hex_or_oct_or_bin)) && \
111  (power(2, signed?width-1:width)>value_abs))
112 
113  unsigned width;
114  bool is_signed=false;
115  irep_idt c_type;
116 
117  if(FITS(config.ansi_c.int_width, true) && long_cnt==0) // int
118  {
119  width=config.ansi_c.int_width;
120  is_signed=true;
121  c_type=ID_signed_int;
122  }
123  else if(FITS(config.ansi_c.int_width, false) && long_cnt==0) // unsigned int
124  {
125  width=config.ansi_c.int_width;
126  is_signed=false;
127  c_type=ID_unsigned_int;
128  }
129  else if(FITS(config.ansi_c.long_int_width, true) && long_cnt!=2) // long int
130  {
132  is_signed=true;
133  c_type=ID_signed_long_int;
134  }
135  // unsigned long int
136  else if(FITS(config.ansi_c.long_int_width, false) && long_cnt!=2)
137  {
139  is_signed=false;
140  c_type=ID_unsigned_long_int;
141  }
142  else if(FITS(config.ansi_c.long_long_int_width, true)) // long long int
143  {
145  is_signed=true;
146  c_type=ID_signed_long_long_int;
147  }
148  // unsigned long long int
149  else if(FITS(config.ansi_c.long_long_int_width, false))
150  {
152  is_signed=false;
153  c_type=ID_unsigned_long_long_int;
154  }
155  else
156  {
157  // Way too large. Should consider issuing a warning.
159 
160  if(is_unsigned)
161  {
162  is_signed=false;
163  c_type=ID_unsigned_long_long_int;
164  }
165  else
166  c_type=ID_signed_long_long_int;
167  }
168 
169  bitvector_typet type(is_signed ? ID_signedbv : ID_unsignedbv, width);
170  type.set(ID_C_c_type, c_type);
171 
172  exprt result;
173 
174  if(is_imaginary)
175  {
176  result = complex_exprt(
177  from_integer(0, type), from_integer(value, type), complex_typet(type));
178  }
179  else
180  {
181  result=from_integer(value, type);
182  result.set(ID_C_base, base);
183  }
184 
185  return result;
186 }
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:37
arith_tools.h
mp_integer
BigInt mp_integer
Definition: mp_arith.h:19
is_signed
bool is_signed(const typet &t)
Convenience function – is the type signed?
Definition: util.cpp:45
string2integer
const mp_integer string2integer(const std::string &n, unsigned base)
Definition: mp_arith.cpp:57
convert_integer_literal.h
C++ Language Conversion.
exprt
Base class for all expressions.
Definition: expr.h:53
complex_typet
Complex numbers made of pair of given subtype.
Definition: std_types.h:1790
configt::ansi_c
struct configt::ansi_ct ansi_c
string2int.h
std_types.h
Pre-defined types.
is_unsigned
bool is_unsigned(const typet &t)
Convenience function – is the type unsigned?
Definition: util.cpp:52
configt::ansi_ct::long_long_int_width
std::size_t long_long_int_width
Definition: config.h:36
complex_exprt
Complex constructor from a pair of numbers.
Definition: std_expr.h:1672
config
configt config
Definition: config.cpp:24
bitvector_typet
Base class of fixed-width bit-vector types.
Definition: std_types.h:1030
irept::set
void set(const irep_namet &name, const irep_idt &value)
Definition: irep.h:442
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:99
unsafe_string2unsigned
unsigned unsafe_string2unsigned(const std::string &str, int base)
Definition: string2int.cpp:38
config.h
convert_integer_literal
exprt convert_integer_literal(const std::string &src)
Definition: convert_integer_literal.cpp:23
FITS
#define FITS(width, signed)
std_expr.h
API to expression classes.
configt::ansi_ct::int_width
std::size_t int_width
Definition: config.h:31
configt::ansi_ct::long_int_width
std::size_t long_int_width
Definition: config.h:32