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_string2int(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  typet type=typet(is_unsigned?ID_unsignedbv:ID_signedbv);
94  type.set(ID_width, 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  typet type=typet(is_signed?ID_signedbv:ID_unsignedbv);
170 
171  type.set(ID_width, width);
172  type.set(ID_C_c_type, c_type);
173 
174  exprt result;
175 
176  if(is_imaginary)
177  {
178  complex_typet complex_type;
179  complex_type.subtype()=type;
180  result=exprt(ID_complex, complex_type);
181  result.operands().resize(2);
182  result.op0()=from_integer(0, type);
183  result.op1()=from_integer(value, type);
184  }
185  else
186  {
187  result=from_integer(value, type);
188  result.set(ID_C_base, base);
189  }
190 
191  return result;
192 }
The type of an expression.
Definition: type.h:22
bool is_signed(const typet &t)
Convenience function – is the type signed?
Definition: util.cpp:45
struct configt::ansi_ct ansi_c
BigInt mp_integer
Definition: mp_arith.h:22
const mp_integer string2integer(const std::string &n, unsigned base)
Definition: mp_arith.cpp:57
exprt & op0()
Definition: expr.h:72
#define FITS(width, signed)
configt config
Definition: config.cpp:23
std::size_t long_long_int_width
Definition: config.h:35
API to expression classes.
exprt & op1()
Definition: expr.h:75
std::size_t int_width
Definition: config.h:30
bool is_unsigned(const typet &t)
Convenience function – is the type unsigned?
Definition: util.cpp:52
Complex numbers made of pair of given subtype.
Definition: std_types.h:1677
API to type classes.
Base class for all expressions.
Definition: expr.h:42
exprt convert_integer_literal(const std::string &src)
const typet & subtype() const
Definition: type.h:33
C++ Language Conversion.
operandst & operands()
Definition: expr.h:66
std::size_t long_int_width
Definition: config.h:31
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
int unsafe_string2int(const std::string &str, int base)
Definition: string2int.cpp:64
void set(const irep_namet &name, const irep_idt &value)
Definition: irep.h:214