C front-end: Do not wrongly propagate const-ness

This bug has been lingering for a longer time, but only started showing up with
the propagation fix in 2c16231b48.

1. Qualifiers (and const-ness in particular) are a property of the type, and not
an expression. Make sure all uses of ID_C_constant affect the type.
2. Qualifiers go with the type of the symbol being declared, and aren't a
property that applies across uses of the same type.
This commit is contained in:
Michael Tautschnig 2018-10-03 08:45:40 +00:00
parent 0e695d08f7
commit 03d4b70a7e
8 changed files with 77 additions and 17 deletions

View File

@ -0,0 +1,36 @@
#if TEST == 0
const struct buffer *foo();
typedef struct buffer
{
int head;
} buffer_t;
#endif
#if TEST == 1
struct buffer *foo();
typedef struct buffer
{
int head;
} buffer_t;
#endif
#if TEST == 2
typedef struct buffer
{
int head;
} buffer_t;
const struct buffer *foo();
#endif
static void clear(buffer_t *buf)
{
buf->head = 0u;
}
int main()
{
return 0;
}

View File

@ -0,0 +1,7 @@
CORE
main.c
-DTEST=0
^EXIT=0$
^SIGNAL=0$
--
^.*: .* is constant$

View File

@ -0,0 +1,7 @@
CORE
main.c
-DTEST=1
^EXIT=0$
^SIGNAL=0$
--
^.*: .* is constant$

View File

@ -0,0 +1,7 @@
CORE
main.c
-DTEST=2
^EXIT=0$
^SIGNAL=0$
--
^.*: .* is constant$

View File

@ -29,10 +29,11 @@ static exprt make_member_expr(
const typet &type=
ns.follow(struct_union.type());
if(result.get_bool(ID_C_constant) ||
type.get_bool(ID_C_constant) ||
struct_union.type().get_bool(ID_C_constant))
result.set(ID_C_constant, true);
if(
type.get_bool(ID_C_constant) || struct_union.type().get_bool(ID_C_constant))
{
result.type().set(ID_C_constant, true);
}
return result;
}

View File

@ -555,12 +555,6 @@ void c_typecastt::implicit_typecast_followed(
// check qualifiers
/*
if(src_type.subtype().get_bool(ID_C_constant) &&
!dest_type.subtype().get_bool(ID_C_constant))
warnings.push_back("disregarding const");
*/
if(src_type.subtype().get_bool(ID_C_volatile) &&
!dest_type.subtype().get_bool(ID_C_volatile))
warnings.push_back("disregarding volatile");

View File

@ -358,8 +358,8 @@ void c_typecheck_baset::typecheck_expr_main(exprt &expr)
if(op.get_bool(ID_C_lvalue))
complex_real_expr.set(ID_C_lvalue, true);
if(op.get_bool(ID_C_constant))
complex_real_expr.set(ID_C_constant, true);
if(op.type().get_bool(ID_C_constant))
complex_real_expr.type().set(ID_C_constant, true);
expr.swap(complex_real_expr);
}
@ -396,8 +396,8 @@ void c_typecheck_baset::typecheck_expr_main(exprt &expr)
if(op.get_bool(ID_C_lvalue))
complex_imag_expr.set(ID_C_lvalue, true);
if(op.get_bool(ID_C_constant))
complex_imag_expr.set(ID_C_constant, true);
if(op.type().get_bool(ID_C_constant))
complex_imag_expr.type().set(ID_C_constant, true);
expr.swap(complex_imag_expr);
}
@ -2853,7 +2853,7 @@ void c_typecheck_baset::typecheck_function_call_arguments(
if(type.id()==ID_array)
{
typet dest_type=pointer_type(void_type());
dest_type.subtype().set(ID_C_constant, ID_1);
dest_type.subtype().set(ID_C_constant, true);
implicit_typecast(op, dest_type);
}
}

View File

@ -722,6 +722,16 @@ void c_typecheck_baset::typecheck_compound_type(struct_union_typet &type)
bool have_body=type.find(ID_components).is_not_nil();
c_qualifierst original_qualifiers(type);
// the type symbol, which may get re-used in other declarations, must not
// carry any qualifiers (other than transparent_union, which isn't really a
// qualifier)
c_qualifierst remove_qualifiers;
remove_qualifiers.is_transparent_union =
original_qualifiers.is_transparent_union;
remove_qualifiers.write(type);
if(type.find(ID_tag).is_nil())
{
// Anonymous? Must come with body.
@ -818,8 +828,6 @@ void c_typecheck_baset::typecheck_compound_type(struct_union_typet &type)
}
}
c_qualifierst original_qualifiers(type);
typet tag_type;
if(type.id() == ID_union || type.id() == ID_incomplete_union)