-
Notifications
You must be signed in to change notification settings - Fork 273
Move promotion rule application to C front-end [blocks: #3725, #3800] #3770
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
KNOWNBUG | ||
CORE | ||
main.c | ||
--signed-overflow-check --conversion-check | ||
^EXIT=10$ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#include <assert.h> | ||
|
||
enum E | ||
{ | ||
A = 1, | ||
B = 16 | ||
}; | ||
|
||
int main() | ||
{ | ||
enum E e = A; | ||
e <<= 4; | ||
assert(e == B); | ||
e >>= 4; | ||
assert(e == A); | ||
e |= B; | ||
e ^= A; | ||
assert(e == B); | ||
e -= 15; | ||
assert(e == A); | ||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
CORE | ||
main.c | ||
|
||
^EXIT=0$ | ||
^SIGNAL=0$ | ||
^VERIFICATION SUCCESSFUL$ | ||
-- | ||
^warning: ignoring |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,10 +44,13 @@ void goto_convertt::remove_assignment( | |
|
||
if(statement==ID_assign) | ||
{ | ||
exprt tmp=expr; | ||
tmp.id(ID_code); | ||
// just interpret as code | ||
convert_assign(to_code_assign(to_code(tmp)), dest, mode); | ||
exprt new_lhs = skip_typecast(expr.op0()); | ||
exprt new_rhs = | ||
typecast_exprt::conditional_cast(expr.op1(), new_lhs.type()); | ||
code_assignt assign(std::move(new_lhs), std::move(new_rhs)); | ||
assign.add_source_location() = expr.source_location(); | ||
|
||
convert_assign(assign, dest, mode); | ||
} | ||
else if(statement==ID_assign_plus || | ||
statement==ID_assign_minus || | ||
|
@@ -99,33 +102,19 @@ void goto_convertt::remove_assignment( | |
|
||
const typet &op0_type = expr.op0().type(); | ||
|
||
if(op0_type.id()==ID_c_bool) | ||
{ | ||
// C/C++ Booleans get very special treatment. | ||
binary_exprt tmp(expr.op0(), new_id, expr.op1(), expr.op1().type()); | ||
tmp.op0().make_typecast(expr.op1().type()); | ||
rhs=typecast_exprt(is_not_zero(tmp, ns), expr.op0().type()); | ||
} | ||
else if(op0_type.id() == ID_c_enum_tag) | ||
{ | ||
// We convert c_enums to their underlying type, do the | ||
// operation, and then convert back | ||
const auto &enum_type = ns.follow_tag(to_c_enum_tag_type(op0_type)); | ||
auto underlying_type = enum_type.subtype(); | ||
auto op0 = typecast_exprt(expr.op0(), underlying_type); | ||
auto op1 = typecast_exprt(expr.op1(), underlying_type); | ||
binary_exprt tmp(op0, new_id, op1, underlying_type); | ||
rhs = typecast_exprt(tmp, expr.op0().type()); | ||
} | ||
else | ||
{ | ||
rhs.id(new_id); | ||
rhs.copy_to_operands(expr.op0(), expr.op1()); | ||
rhs.type()=expr.op0().type(); | ||
rhs.add_source_location()=expr.source_location(); | ||
} | ||
PRECONDITION( | ||
op0_type.id() != ID_c_enum_tag && op0_type.id() != ID_c_enum && | ||
op0_type.id() != ID_c_bool && op0_type.id() != ID_bool); | ||
rhs.id(new_id); | ||
rhs.copy_to_operands(expr.op0(), expr.op1()); | ||
rhs.type() = expr.op0().type(); | ||
rhs.add_source_location() = expr.source_location(); | ||
|
||
exprt new_lhs = skip_typecast(expr.op0()); | ||
rhs = typecast_exprt::conditional_cast(rhs, new_lhs.type()); | ||
rhs.add_source_location() = expr.source_location(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is outside the C front-end, I don't think I can use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, you may have to add |
||
|
||
code_assignt assignment(expr.op0(), rhs); | ||
code_assignt assignment(new_lhs, rhs); | ||
assignment.add_source_location()=expr.source_location(); | ||
|
||
convert(assignment, dest, mode); | ||
|
@@ -171,45 +160,34 @@ void goto_convertt::remove_pre( | |
|
||
const typet &op_type = expr.op0().type(); | ||
|
||
if(op_type.id()==ID_bool) | ||
{ | ||
rhs.copy_to_operands(expr.op0(), from_integer(1, signed_int_type())); | ||
rhs.op0().make_typecast(signed_int_type()); | ||
rhs.type()=signed_int_type(); | ||
rhs=is_not_zero(rhs, ns); | ||
} | ||
else if(op_type.id()==ID_c_bool) | ||
PRECONDITION( | ||
op_type.id() != ID_c_enum_tag && op_type.id() != ID_c_enum && | ||
op_type.id() != ID_c_bool && op_type.id() != ID_bool); | ||
|
||
typet constant_type; | ||
|
||
if(op_type.id() == ID_pointer) | ||
constant_type = index_type(); | ||
else if(is_number(op_type)) | ||
constant_type = op_type; | ||
else | ||
{ | ||
rhs.copy_to_operands(expr.op0(), from_integer(1, signed_int_type())); | ||
rhs.op0().make_typecast(signed_int_type()); | ||
rhs.type()=signed_int_type(); | ||
rhs=is_not_zero(rhs, ns); | ||
rhs.make_typecast(op_type); | ||
UNREACHABLE; | ||
} | ||
else if(op_type.id()==ID_c_enum || | ||
op_type.id()==ID_c_enum_tag) | ||
|
||
exprt constant; | ||
|
||
if(constant_type.id() == ID_complex) | ||
{ | ||
rhs.copy_to_operands(expr.op0(), from_integer(1, signed_int_type())); | ||
rhs.op0().make_typecast(signed_int_type()); | ||
rhs.type()=signed_int_type(); | ||
rhs.make_typecast(op_type); | ||
exprt real = from_integer(1, constant_type.subtype()); | ||
exprt imag = from_integer(0, constant_type.subtype()); | ||
constant = complex_exprt(real, imag, to_complex_type(constant_type)); | ||
} | ||
else | ||
{ | ||
typet constant_type; | ||
|
||
if(op_type.id()==ID_pointer) | ||
constant_type=index_type(); | ||
else if(is_number(op_type) || op_type.id()==ID_c_bool) | ||
constant_type=op_type; | ||
else | ||
{ | ||
UNREACHABLE; | ||
} | ||
constant = from_integer(1, constant_type); | ||
|
||
rhs.add_to_operands(expr.op0(), from_integer(1, constant_type)); | ||
rhs.type()=expr.op0().type(); | ||
} | ||
rhs.add_to_operands(expr.op0(), std::move(constant)); | ||
rhs.type() = expr.op0().type(); | ||
|
||
code_assignt assignment(expr.op0(), rhs); | ||
assignment.add_source_location()=expr.find_source_location(); | ||
|
@@ -257,56 +235,34 @@ void goto_convertt::remove_post( | |
|
||
const typet &op_type = expr.op0().type(); | ||
|
||
if(op_type.id()==ID_bool) | ||
{ | ||
rhs.copy_to_operands(expr.op0(), from_integer(1, signed_int_type())); | ||
rhs.op0().make_typecast(signed_int_type()); | ||
rhs.type()=signed_int_type(); | ||
rhs=is_not_zero(rhs, ns); | ||
} | ||
else if(op_type.id()==ID_c_bool) | ||
PRECONDITION( | ||
op_type.id() != ID_c_enum_tag && op_type.id() != ID_c_enum && | ||
op_type.id() != ID_c_bool && op_type.id() != ID_bool); | ||
|
||
typet constant_type; | ||
|
||
if(op_type.id() == ID_pointer) | ||
constant_type = index_type(); | ||
else if(is_number(op_type)) | ||
constant_type = op_type; | ||
else | ||
{ | ||
rhs.copy_to_operands(expr.op0(), from_integer(1, signed_int_type())); | ||
rhs.op0().make_typecast(signed_int_type()); | ||
rhs.type()=signed_int_type(); | ||
rhs=is_not_zero(rhs, ns); | ||
rhs.make_typecast(op_type); | ||
UNREACHABLE; | ||
} | ||
else if(op_type.id()==ID_c_enum || | ||
op_type.id()==ID_c_enum_tag) | ||
|
||
exprt constant; | ||
|
||
if(constant_type.id() == ID_complex) | ||
{ | ||
rhs.copy_to_operands(expr.op0(), from_integer(1, signed_int_type())); | ||
rhs.op0().make_typecast(signed_int_type()); | ||
rhs.type()=signed_int_type(); | ||
rhs.make_typecast(op_type); | ||
exprt real = from_integer(1, constant_type.subtype()); | ||
exprt imag = from_integer(0, constant_type.subtype()); | ||
constant = complex_exprt(real, imag, to_complex_type(constant_type)); | ||
} | ||
else | ||
{ | ||
typet constant_type; | ||
constant = from_integer(1, constant_type); | ||
|
||
if(op_type.id()==ID_pointer) | ||
constant_type=index_type(); | ||
else if(is_number(op_type) || op_type.id()==ID_c_bool) | ||
constant_type=op_type; | ||
else | ||
{ | ||
UNREACHABLE; | ||
} | ||
|
||
exprt constant; | ||
|
||
if(constant_type.id()==ID_complex) | ||
{ | ||
exprt real=from_integer(1, constant_type.subtype()); | ||
exprt imag=from_integer(0, constant_type.subtype()); | ||
constant=complex_exprt(real, imag, to_complex_type(constant_type)); | ||
} | ||
else | ||
constant=from_integer(1, constant_type); | ||
|
||
rhs.add_to_operands(expr.op0(), std::move(constant)); | ||
rhs.type()=expr.op0().type(); | ||
} | ||
rhs.add_to_operands(expr.op0(), std::move(constant)); | ||
rhs.type() = expr.op0().type(); | ||
|
||
code_assignt assignment(expr.op0(), rhs); | ||
assignment.add_source_location()=expr.find_source_location(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would make that an implicit typecast.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added
implicit_typecast_arithmetic(expr);
- is that what you expected?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, that's arithmetic promotion; I am not actually sure whether these are meant to happen to the underlying type of an enum.
What I meant is the
ID_C_implicit_typecast
annotation, which is used to distinguish an explicit cast from one added by the frontend.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't seem to find
ID_C_implicit_typecast
or indeed any other annotation that theimplicit_typecast
code would be adding?!