Skip to content

Commit 4c51ce9

Browse files
authored
Merge pull request #5677 from tautschnig/static-assert
_Static_assert failures should be reported in the front-end
2 parents cc16a46 + d80f750 commit 4c51ce9

14 files changed

+106
-24
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
_Static_assert(1 == 0, "must fail");
2+
3+
int main()
4+
{
5+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE gcc-only
2+
global.c
3+
4+
static assertion failed: must fail
5+
^CONVERSION ERROR$
6+
^EXIT=(1|64)$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring
10+
Invariant check failed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
int main()
2+
{
3+
_Static_assert(1 == 0, "must fail");
4+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE gcc-only
2+
local.c
3+
4+
static assertion failed: must fail
5+
^CONVERSION ERROR$
6+
^EXIT=(1|64)$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring
10+
Invariant check failed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
int main()
2+
{
3+
int x;
4+
_Static_assert(x, "must fail");
5+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE gcc-only
2+
not_constant.c
3+
4+
expected constant expression
5+
^CONVERSION ERROR$
6+
^EXIT=(1|64)$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring
10+
Invariant check failed

regression/cbmc-library/Float_lib1/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ int main()
4343

4444
_Static_assert(__builtin_isnormal(DBL_MIN), "__builtin_isnormal is constant");
4545

46-
_Static_assert(!__builtin_isinf(0), "__builtin_isinf is constant");
46+
_Static_assert(!__builtin_isinf(0.0), "__builtin_isinf is constant");
4747

4848
_Static_assert(
49-
__builtin_isinf_sign(0) == 0, "__builtin_isinf_sign is constant");
49+
__builtin_isinf_sign(0.0) == 0, "__builtin_isinf_sign is constant");
5050

5151
#endif
5252

src/ansi-c/c_typecheck_base.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -634,9 +634,10 @@ void c_typecheck_baset::typecheck_declaration(
634634
{
635635
if(declaration.get_is_static_assert())
636636
{
637-
auto &static_assert_expr = to_binary_expr(declaration);
638-
typecheck_expr(static_assert_expr.op0());
639-
typecheck_expr(static_assert_expr.op1());
637+
codet code(ID_static_assert);
638+
code.add_source_location() = declaration.source_location();
639+
code.operands().swap(declaration.operands());
640+
typecheck_code(code);
640641
}
641642
else
642643
{

src/ansi-c/c_typecheck_code.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Author: Daniel Kroening, [email protected]
1515
#include <util/config.h>
1616
#include <util/expr_initializer.h>
1717
#include <util/range.h>
18+
#include <util/string_constant.h>
1819

1920
#include "ansi_c_declaration.h"
2021

@@ -102,9 +103,24 @@ void c_typecheck_baset::typecheck_code(codet &code)
102103
}
103104
else if(statement==ID_static_assert)
104105
{
105-
assert(code.operands().size()==2);
106+
PRECONDITION(code.operands().size() == 2);
107+
106108
typecheck_expr(code.op0());
107109
typecheck_expr(code.op1());
110+
111+
implicit_typecast_bool(code.op0());
112+
make_constant(code.op0());
113+
114+
if(code.op0().is_false())
115+
{
116+
// failed
117+
error().source_location = code.find_source_location();
118+
error() << "static assertion failed";
119+
if(code.op1().id() == ID_string_constant)
120+
error() << ": " << to_string_constant(code.op1()).get_value();
121+
error() << eom;
122+
throw 0;
123+
}
108124
}
109125
else if(statement==ID_CPROVER_try_catch ||
110126
statement==ID_CPROVER_try_finally)
@@ -247,7 +263,6 @@ void c_typecheck_baset::typecheck_decl(codet &code)
247263

248264
if(declaration.get_is_static_assert())
249265
{
250-
assert(declaration.operands().size()==2);
251266
codet new_code(ID_static_assert);
252267
new_code.add_source_location()=code.source_location();
253268
new_code.operands().swap(declaration.operands());

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2457,6 +2457,15 @@ exprt c_typecheck_baset::do_special_functions(
24572457

24582458
typecheck_function_call_arguments(expr);
24592459

2460+
const exprt &fp_value = expr.arguments().front();
2461+
2462+
if(fp_value.type().id() != ID_floatbv)
2463+
{
2464+
error().source_location = fp_value.source_location();
2465+
error() << "non-floating-point argument for " << identifier << eom;
2466+
throw 0;
2467+
}
2468+
24602469
isinf_exprt isinf_expr(expr.arguments().front());
24612470
isinf_expr.add_source_location()=source_location;
24622471

@@ -2477,6 +2486,13 @@ exprt c_typecheck_baset::do_special_functions(
24772486

24782487
const exprt &fp_value = expr.arguments().front();
24792488

2489+
if(fp_value.type().id() != ID_floatbv)
2490+
{
2491+
error().source_location = fp_value.source_location();
2492+
error() << "non-floating-point argument for " << identifier << eom;
2493+
throw 0;
2494+
}
2495+
24802496
isinf_exprt isinf_expr(fp_value);
24812497
isinf_expr.add_source_location() = source_location;
24822498

src/ansi-c/c_typecheck_type.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,13 @@ void c_typecheck_baset::typecheck_compound_body(
10361036
{
10371037
if(it->id()==ID_static_assert)
10381038
{
1039+
if(config.ansi_c.mode == configt::ansi_ct::flavourt::VISUAL_STUDIO)
1040+
{
1041+
error().source_location = it->source_location();
1042+
error() << "static_assert not supported in compound body" << eom;
1043+
throw 0;
1044+
}
1045+
10391046
exprt &assertion = to_binary_expr(*it).op0();
10401047
typecheck_expr(assertion);
10411048
typecheck_expr(to_binary_expr(*it).op1());

src/ansi-c/scanner.l

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,15 @@ or_eq { return cpp98_keyword(TOK_ORASSIGN); }
852852
private { return cpp98_keyword(TOK_PRIVATE); }
853853
protected { return cpp98_keyword(TOK_PROTECTED); }
854854
public { return cpp98_keyword(TOK_PUBLIC); }
855-
static_assert { return cpp11_keyword(TOK_STATIC_ASSERT); } // C++11
855+
static_assert { // C++11, but Visual Studio supports it in all modes (and
856+
// doesn't support _Static_assert)
857+
if(PARSER.mode == configt::ansi_ct::flavourt::VISUAL_STUDIO)
858+
{
859+
loc(); return TOK_STATIC_ASSERT;
860+
}
861+
else
862+
return cpp11_keyword(TOK_STATIC_ASSERT);
863+
}
856864
template { return cpp98_keyword(TOK_TEMPLATE); }
857865
this { return cpp98_keyword(TOK_THIS); }
858866
thread_local { return cpp11_keyword(TOK_THREAD_LOCAL); } // C++11

src/cpp/cpp_typecheck_static_assert.cpp

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,10 @@ void cpp_typecheckt::convert(cpp_static_assertt &cpp_static_assert)
1919
typecheck_expr(cpp_static_assert.op0());
2020
typecheck_expr(cpp_static_assert.op1());
2121

22-
cpp_static_assert.op0() =
23-
typecast_exprt::conditional_cast(cpp_static_assert.op0(), bool_typet());
22+
implicit_typecast_bool(cpp_static_assert.op0());
2423
make_constant(cpp_static_assert.op0());
2524

26-
if(cpp_static_assert.op0().is_true())
27-
{
28-
// ok
29-
}
30-
else if(cpp_static_assert.op0().is_false())
25+
if(cpp_static_assert.op0().is_false())
3126
{
3227
// failed
3328
error().source_location=cpp_static_assert.source_location();
@@ -38,11 +33,4 @@ void cpp_typecheckt::convert(cpp_static_assertt &cpp_static_assert)
3833
error() << eom;
3934
throw 0;
4035
}
41-
else
42-
{
43-
// not true or false
44-
error().source_location=cpp_static_assert.source_location();
45-
error() << "static assertion is not constant" << eom;
46-
throw 0;
47-
}
4836
}

src/util/simplify_expr_floatbv.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ Author: Daniel Kroening, [email protected]
2020
simplify_exprt::resultt<>
2121
simplify_exprt::simplify_isinf(const unary_exprt &expr)
2222
{
23-
if(expr.op().type().id() != ID_floatbv)
24-
return unchanged(expr);
23+
PRECONDITION(expr.op().type().id() == ID_floatbv);
2524

2625
if(expr.op().is_constant())
2726
{
@@ -35,6 +34,8 @@ simplify_exprt::simplify_isinf(const unary_exprt &expr)
3534
simplify_exprt::resultt<>
3635
simplify_exprt::simplify_isnan(const unary_exprt &expr)
3736
{
37+
PRECONDITION(expr.op().type().id() == ID_floatbv);
38+
3839
if(expr.op().is_constant())
3940
{
4041
ieee_floatt value(to_constant_expr(expr.op()));
@@ -47,6 +48,8 @@ simplify_exprt::simplify_isnan(const unary_exprt &expr)
4748
simplify_exprt::resultt<>
4849
simplify_exprt::simplify_isnormal(const unary_exprt &expr)
4950
{
51+
PRECONDITION(expr.op().type().id() == ID_floatbv);
52+
5053
if(expr.op().is_constant())
5154
{
5255
ieee_floatt value(to_constant_expr(expr.op()));

0 commit comments

Comments
 (0)