Skip to content

Commit 8aab2e5

Browse files
authored
Merge pull request #6461 from tautschnig/local-static
Static-lifetime symbols require compile-time constant initialisers
2 parents f562bcf + 1a86739 commit 8aab2e5

File tree

5 files changed

+61
-7
lines changed

5 files changed

+61
-7
lines changed

regression/ansi-c/static4/main.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
int main()
2+
{
3+
int y = 42;
4+
static int x = y;
5+
6+
__CPROVER_assert(x == 42, "local static");
7+
}

regression/ansi-c/static4/test.desc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
4+
expected constant expression
5+
^CONVERSION ERROR$
6+
^EXIT=(1|64)$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring

src/ansi-c/c_typecheck_code.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,12 +308,19 @@ void c_typecheck_baset::typecheck_decl(codet &code)
308308
// see if it's a typedef
309309
// or a function
310310
// or static
311-
if(symbol.is_type ||
312-
symbol.type.id()==ID_code ||
313-
symbol.is_static_lifetime)
311+
if(symbol.is_type || symbol.type.id() == ID_code)
314312
{
315313
// we ignore
316314
}
315+
else if(symbol.is_static_lifetime)
316+
{
317+
// make sure the initialization value is a compile-time constant
318+
if(symbol.value.is_not_nil())
319+
{
320+
exprt init_value = symbol.value;
321+
make_constant(init_value);
322+
}
323+
}
317324
else
318325
{
319326
code_frontend_declt decl(symbol.symbol_expr());

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3925,6 +3925,38 @@ void c_typecheck_baset::typecheck_side_effect_assignment(
39253925
throw 0;
39263926
}
39273927

3928+
class is_compile_time_constantt : public is_constantt
3929+
{
3930+
public:
3931+
explicit is_compile_time_constantt(const namespacet &ns) : ns(ns)
3932+
{
3933+
}
3934+
3935+
protected:
3936+
const namespacet &ns;
3937+
3938+
bool is_constant(const exprt &e) const override
3939+
{
3940+
if(e.id() == ID_infinity)
3941+
return true;
3942+
else
3943+
return is_constantt::is_constant(e);
3944+
}
3945+
3946+
bool is_constant_address_of(const exprt &e) const override
3947+
{
3948+
if(e.id() == ID_symbol)
3949+
{
3950+
return e.type().id() == ID_code ||
3951+
ns.lookup(to_symbol_expr(e).get_identifier()).is_static_lifetime;
3952+
}
3953+
else if(e.id() == ID_array && e.get_bool(ID_C_string_constant))
3954+
return true;
3955+
else
3956+
return is_constantt::is_constant_address_of(e);
3957+
}
3958+
};
3959+
39283960
void c_typecheck_baset::make_constant(exprt &expr)
39293961
{
39303962
// Floating-point expressions may require a rounding mode.
@@ -3936,8 +3968,7 @@ void c_typecheck_baset::make_constant(exprt &expr)
39363968

39373969
simplify(expr, *this);
39383970

3939-
if(!expr.is_constant() &&
3940-
expr.id()!=ID_infinity)
3971+
if(!is_compile_time_constantt(*this)(expr))
39413972
{
39423973
error().source_location=expr.find_source_location();
39433974
error() << "expected constant expression, but got '" << to_string(expr)
@@ -3952,8 +3983,7 @@ void c_typecheck_baset::make_constant_index(exprt &expr)
39523983
make_index_type(expr);
39533984
simplify(expr, *this);
39543985

3955-
if(!expr.is_constant() &&
3956-
expr.id()!=ID_infinity)
3986+
if(!is_compile_time_constantt(*this)(expr))
39573987
{
39583988
error().source_location=expr.find_source_location();
39593989
error() << "conversion to integer constant failed" << eom;

src/util/expr_util.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ bool is_constantt::is_constant(const exprt &expr) const
236236
expr.id() == ID_typecast || expr.id() == ID_array_of ||
237237
expr.id() == ID_plus || expr.id() == ID_mult || expr.id() == ID_array ||
238238
expr.id() == ID_with || expr.id() == ID_struct || expr.id() == ID_union ||
239+
expr.id() == ID_empty_union ||
239240
// byte_update works, byte_extract may be out-of-bounds
240241
expr.id() == ID_byte_update_big_endian ||
241242
expr.id() == ID_byte_update_little_endian)

0 commit comments

Comments
 (0)