Skip to content

Commit ba421e0

Browse files
authored
Merge pull request #3770 from tautschnig/cleanup-promotion
Move promotion rule application to C front-end [blocks: #3725, #3800]
2 parents dc4611f + 2043025 commit ba421e0

File tree

6 files changed

+133
-127
lines changed

6 files changed

+133
-127
lines changed

regression/cbmc/Overflow_Addition3/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33
--signed-overflow-check --conversion-check
44
^EXIT=10$

regression/cbmc/complex1/main.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
int main()
44
{
5-
#ifdef __GNUC__
5+
#ifdef __GNUC__
66
_Complex c; // this is usually '_Complex double'
77
c=1.0i+2;
88

@@ -21,10 +21,10 @@ int main()
2121

2222
// The real part is stored first in memory on i386.
2323
// Need to find out about other architectures.
24-
#if defined(__i386__) || defined(__amd64__)
24+
#if defined(__i386__) || defined(__amd64__)
2525
assert(((signed char *)&char_complex)[0]==-2);
2626
assert(((signed char *)&char_complex)[1]==3);
27-
#endif
27+
#endif
2828

2929
assert(__real__ char_complex == -2);
3030
assert(__imag__ char_complex == 3);
@@ -44,18 +44,35 @@ int main()
4444
char_complex++;
4545
assert(__real__ char_complex == 101);
4646
assert(__imag__ char_complex == 3);
47+
++char_complex;
48+
assert(__real__ char_complex == 102);
49+
assert(__imag__ char_complex == 3);
50+
char_complex += 1;
51+
assert(__real__ char_complex == 103);
52+
assert(__imag__ char_complex == 3);
4753

4854
// also separately
4955
(__real__ char_complex)++;
50-
assert(__real__ char_complex == 102);
56+
assert(__real__ char_complex == 104);
5157
assert(__imag__ char_complex == 3);
5258

5359
// casts to reals produce the real part
54-
assert((int) char_complex == 102);
60+
assert((int)char_complex == 104);
61+
62+
// can be decremented
63+
char_complex--;
64+
assert(__real__ char_complex == 103);
65+
assert(__imag__ char_complex == 3);
66+
--char_complex;
67+
assert(__real__ char_complex == 102);
68+
assert(__imag__ char_complex == 3);
69+
char_complex -= 1;
70+
assert(__real__ char_complex == 101);
71+
assert(__imag__ char_complex == 3);
5572

56-
#else
73+
#else
5774

5875
// Visual studio doesn't have it
5976

60-
#endif
77+
#endif
6178
}

regression/cbmc/enum8/main.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <assert.h>
2+
3+
enum E
4+
{
5+
A = 1,
6+
B = 16
7+
};
8+
9+
int main()
10+
{
11+
enum E e = A;
12+
e <<= 4;
13+
assert(e == B);
14+
e >>= 4;
15+
assert(e == A);
16+
e |= B;
17+
e ^= A;
18+
assert(e == B);
19+
e -= 15;
20+
assert(e == A);
21+
return 0;
22+
}

regression/cbmc/enum8/test.desc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1855,16 +1855,19 @@ void c_typecheck_baset::typecheck_expr_side_effect(side_effect_exprt &expr)
18551855

18561856
if(type0.id() == ID_c_enum_tag)
18571857
{
1858-
if(follow_tag(to_c_enum_tag_type(type0)).is_incomplete())
1858+
const c_enum_typet &enum_type = follow_tag(to_c_enum_tag_type(type0));
1859+
if(enum_type.is_incomplete())
18591860
{
18601861
error().source_location = expr.source_location();
18611862
error() << "operator `" << statement
18621863
<< "' given incomplete type `"
18631864
<< to_string(type0) << "'" << eom;
18641865
throw 0;
18651866
}
1866-
else
1867-
expr.type()=type0;
1867+
1868+
// increment/decrement on underlying type
1869+
expr.op0() = typecast_exprt(expr.op0(), enum_type.subtype());
1870+
expr.type() = enum_type.subtype();
18681871
}
18691872
else if(type0.id() == ID_c_bit_field)
18701873
{
@@ -1873,6 +1876,11 @@ void c_typecheck_baset::typecheck_expr_side_effect(side_effect_exprt &expr)
18731876
expr.op0() = typecast_exprt(expr.op0(), underlying_type);
18741877
expr.type()=underlying_type;
18751878
}
1879+
else if(type0.id() == ID_bool || type0.id() == ID_c_bool)
1880+
{
1881+
implicit_typecast_arithmetic(expr.op0());
1882+
expr.type() = expr.op0().type();
1883+
}
18761884
else if(is_numeric_type(type0))
18771885
{
18781886
expr.type()=type0;
@@ -3321,6 +3329,7 @@ void c_typecheck_baset::typecheck_side_effect_assignment(
33213329
else if(statement==ID_assign_shl ||
33223330
statement==ID_assign_shr)
33233331
{
3332+
implicit_typecast_arithmetic(op0);
33243333
implicit_typecast_arithmetic(op1);
33253334

33263335
if(is_number(op1.type()))
@@ -3335,12 +3344,6 @@ void c_typecheck_baset::typecheck_side_effect_assignment(
33353344

33363345
typet underlying_type=op0.type();
33373346

3338-
if(underlying_type.id()==ID_c_enum_tag)
3339-
{
3340-
const auto &c_enum_type = to_c_enum_tag_type(underlying_type);
3341-
underlying_type=c_enum_type.subtype();
3342-
}
3343-
33443347
if(underlying_type.id()==ID_unsignedbv ||
33453348
underlying_type.id()==ID_c_bool)
33463349
{
@@ -3363,7 +3366,7 @@ void c_typecheck_baset::typecheck_side_effect_assignment(
33633366
if(o_type0.id()==ID_bool ||
33643367
o_type0.id()==ID_c_bool)
33653368
{
3366-
implicit_typecast_arithmetic(op1);
3369+
implicit_typecast_arithmetic(op0, op1);
33673370
if(op1.type().id()==ID_bool ||
33683371
op1.type().id()==ID_c_bool ||
33693372
op1.type().id()==ID_c_enum_tag ||
@@ -3376,7 +3379,7 @@ void c_typecheck_baset::typecheck_side_effect_assignment(
33763379
o_type0.id()==ID_signedbv ||
33773380
o_type0.id()==ID_c_bit_field)
33783381
{
3379-
implicit_typecast(op1, o_type0);
3382+
implicit_typecast_arithmetic(op0, op1);
33803383
return;
33813384
}
33823385
else if(o_type0.id()==ID_vector &&
@@ -3413,7 +3416,7 @@ void c_typecheck_baset::typecheck_side_effect_assignment(
34133416
else if(o_type0.id()==ID_bool ||
34143417
o_type0.id()==ID_c_bool)
34153418
{
3416-
implicit_typecast_arithmetic(op1);
3419+
implicit_typecast_arithmetic(op0, op1);
34173420
if(op1.type().id()==ID_bool ||
34183421
op1.type().id()==ID_c_bool ||
34193422
op1.type().id()==ID_c_enum_tag ||

src/goto-programs/goto_convert_side_effect.cpp

Lines changed: 63 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,13 @@ void goto_convertt::remove_assignment(
4444

4545
if(statement==ID_assign)
4646
{
47-
exprt tmp=expr;
48-
tmp.id(ID_code);
49-
// just interpret as code
50-
convert_assign(to_code_assign(to_code(tmp)), dest, mode);
47+
exprt new_lhs = skip_typecast(expr.op0());
48+
exprt new_rhs =
49+
typecast_exprt::conditional_cast(expr.op1(), new_lhs.type());
50+
code_assignt assign(std::move(new_lhs), std::move(new_rhs));
51+
assign.add_source_location() = expr.source_location();
52+
53+
convert_assign(assign, dest, mode);
5154
}
5255
else if(statement==ID_assign_plus ||
5356
statement==ID_assign_minus ||
@@ -99,33 +102,19 @@ void goto_convertt::remove_assignment(
99102

100103
const typet &op0_type = expr.op0().type();
101104

102-
if(op0_type.id()==ID_c_bool)
103-
{
104-
// C/C++ Booleans get very special treatment.
105-
binary_exprt tmp(expr.op0(), new_id, expr.op1(), expr.op1().type());
106-
tmp.op0().make_typecast(expr.op1().type());
107-
rhs=typecast_exprt(is_not_zero(tmp, ns), expr.op0().type());
108-
}
109-
else if(op0_type.id() == ID_c_enum_tag)
110-
{
111-
// We convert c_enums to their underlying type, do the
112-
// operation, and then convert back
113-
const auto &enum_type = ns.follow_tag(to_c_enum_tag_type(op0_type));
114-
auto underlying_type = enum_type.subtype();
115-
auto op0 = typecast_exprt(expr.op0(), underlying_type);
116-
auto op1 = typecast_exprt(expr.op1(), underlying_type);
117-
binary_exprt tmp(op0, new_id, op1, underlying_type);
118-
rhs = typecast_exprt(tmp, expr.op0().type());
119-
}
120-
else
121-
{
122-
rhs.id(new_id);
123-
rhs.copy_to_operands(expr.op0(), expr.op1());
124-
rhs.type()=expr.op0().type();
125-
rhs.add_source_location()=expr.source_location();
126-
}
105+
PRECONDITION(
106+
op0_type.id() != ID_c_enum_tag && op0_type.id() != ID_c_enum &&
107+
op0_type.id() != ID_c_bool && op0_type.id() != ID_bool);
108+
rhs.id(new_id);
109+
rhs.copy_to_operands(expr.op0(), expr.op1());
110+
rhs.type() = expr.op0().type();
111+
rhs.add_source_location() = expr.source_location();
112+
113+
exprt new_lhs = skip_typecast(expr.op0());
114+
rhs = typecast_exprt::conditional_cast(rhs, new_lhs.type());
115+
rhs.add_source_location() = expr.source_location();
127116

128-
code_assignt assignment(expr.op0(), rhs);
117+
code_assignt assignment(new_lhs, rhs);
129118
assignment.add_source_location()=expr.source_location();
130119

131120
convert(assignment, dest, mode);
@@ -171,45 +160,34 @@ void goto_convertt::remove_pre(
171160

172161
const typet &op_type = expr.op0().type();
173162

174-
if(op_type.id()==ID_bool)
175-
{
176-
rhs.copy_to_operands(expr.op0(), from_integer(1, signed_int_type()));
177-
rhs.op0().make_typecast(signed_int_type());
178-
rhs.type()=signed_int_type();
179-
rhs=is_not_zero(rhs, ns);
180-
}
181-
else if(op_type.id()==ID_c_bool)
163+
PRECONDITION(
164+
op_type.id() != ID_c_enum_tag && op_type.id() != ID_c_enum &&
165+
op_type.id() != ID_c_bool && op_type.id() != ID_bool);
166+
167+
typet constant_type;
168+
169+
if(op_type.id() == ID_pointer)
170+
constant_type = index_type();
171+
else if(is_number(op_type))
172+
constant_type = op_type;
173+
else
182174
{
183-
rhs.copy_to_operands(expr.op0(), from_integer(1, signed_int_type()));
184-
rhs.op0().make_typecast(signed_int_type());
185-
rhs.type()=signed_int_type();
186-
rhs=is_not_zero(rhs, ns);
187-
rhs.make_typecast(op_type);
175+
UNREACHABLE;
188176
}
189-
else if(op_type.id()==ID_c_enum ||
190-
op_type.id()==ID_c_enum_tag)
177+
178+
exprt constant;
179+
180+
if(constant_type.id() == ID_complex)
191181
{
192-
rhs.copy_to_operands(expr.op0(), from_integer(1, signed_int_type()));
193-
rhs.op0().make_typecast(signed_int_type());
194-
rhs.type()=signed_int_type();
195-
rhs.make_typecast(op_type);
182+
exprt real = from_integer(1, constant_type.subtype());
183+
exprt imag = from_integer(0, constant_type.subtype());
184+
constant = complex_exprt(real, imag, to_complex_type(constant_type));
196185
}
197186
else
198-
{
199-
typet constant_type;
200-
201-
if(op_type.id()==ID_pointer)
202-
constant_type=index_type();
203-
else if(is_number(op_type) || op_type.id()==ID_c_bool)
204-
constant_type=op_type;
205-
else
206-
{
207-
UNREACHABLE;
208-
}
187+
constant = from_integer(1, constant_type);
209188

210-
rhs.add_to_operands(expr.op0(), from_integer(1, constant_type));
211-
rhs.type()=expr.op0().type();
212-
}
189+
rhs.add_to_operands(expr.op0(), std::move(constant));
190+
rhs.type() = expr.op0().type();
213191

214192
code_assignt assignment(expr.op0(), rhs);
215193
assignment.add_source_location()=expr.find_source_location();
@@ -257,56 +235,34 @@ void goto_convertt::remove_post(
257235

258236
const typet &op_type = expr.op0().type();
259237

260-
if(op_type.id()==ID_bool)
261-
{
262-
rhs.copy_to_operands(expr.op0(), from_integer(1, signed_int_type()));
263-
rhs.op0().make_typecast(signed_int_type());
264-
rhs.type()=signed_int_type();
265-
rhs=is_not_zero(rhs, ns);
266-
}
267-
else if(op_type.id()==ID_c_bool)
238+
PRECONDITION(
239+
op_type.id() != ID_c_enum_tag && op_type.id() != ID_c_enum &&
240+
op_type.id() != ID_c_bool && op_type.id() != ID_bool);
241+
242+
typet constant_type;
243+
244+
if(op_type.id() == ID_pointer)
245+
constant_type = index_type();
246+
else if(is_number(op_type))
247+
constant_type = op_type;
248+
else
268249
{
269-
rhs.copy_to_operands(expr.op0(), from_integer(1, signed_int_type()));
270-
rhs.op0().make_typecast(signed_int_type());
271-
rhs.type()=signed_int_type();
272-
rhs=is_not_zero(rhs, ns);
273-
rhs.make_typecast(op_type);
250+
UNREACHABLE;
274251
}
275-
else if(op_type.id()==ID_c_enum ||
276-
op_type.id()==ID_c_enum_tag)
252+
253+
exprt constant;
254+
255+
if(constant_type.id() == ID_complex)
277256
{
278-
rhs.copy_to_operands(expr.op0(), from_integer(1, signed_int_type()));
279-
rhs.op0().make_typecast(signed_int_type());
280-
rhs.type()=signed_int_type();
281-
rhs.make_typecast(op_type);
257+
exprt real = from_integer(1, constant_type.subtype());
258+
exprt imag = from_integer(0, constant_type.subtype());
259+
constant = complex_exprt(real, imag, to_complex_type(constant_type));
282260
}
283261
else
284-
{
285-
typet constant_type;
262+
constant = from_integer(1, constant_type);
286263

287-
if(op_type.id()==ID_pointer)
288-
constant_type=index_type();
289-
else if(is_number(op_type) || op_type.id()==ID_c_bool)
290-
constant_type=op_type;
291-
else
292-
{
293-
UNREACHABLE;
294-
}
295-
296-
exprt constant;
297-
298-
if(constant_type.id()==ID_complex)
299-
{
300-
exprt real=from_integer(1, constant_type.subtype());
301-
exprt imag=from_integer(0, constant_type.subtype());
302-
constant=complex_exprt(real, imag, to_complex_type(constant_type));
303-
}
304-
else
305-
constant=from_integer(1, constant_type);
306-
307-
rhs.add_to_operands(expr.op0(), std::move(constant));
308-
rhs.type()=expr.op0().type();
309-
}
264+
rhs.add_to_operands(expr.op0(), std::move(constant));
265+
rhs.type() = expr.op0().type();
310266

311267
code_assignt assignment(expr.op0(), rhs);
312268
assignment.add_source_location()=expr.find_source_location();

0 commit comments

Comments
 (0)