Skip to content

Commit d80f750

Browse files
committed
_Static_assert failures should be reported in the front-end
We left it to a failing invariant in goto-program conversion to detect a failing (local) _Static_assert. Global _Static_assert statements were not verified at all.
1 parent bd536b8 commit d80f750

11 files changed

+83
-20
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

src/ansi-c/c_typecheck_base.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -627,9 +627,10 @@ void c_typecheck_baset::typecheck_declaration(
627627
{
628628
if(declaration.get_is_static_assert())
629629
{
630-
auto &static_assert_expr = to_binary_expr(declaration);
631-
typecheck_expr(static_assert_expr.op0());
632-
typecheck_expr(static_assert_expr.op1());
630+
codet code(ID_static_assert);
631+
code.add_source_location() = declaration.source_location();
632+
code.operands().swap(declaration.operands());
633+
typecheck_code(code);
633634
}
634635
else
635636
{

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_type.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,13 @@ void c_typecheck_baset::typecheck_compound_body(
10291029
{
10301030
if(it->id()==ID_static_assert)
10311031
{
1032+
if(config.ansi_c.mode == configt::ansi_ct::flavourt::VISUAL_STUDIO)
1033+
{
1034+
error().source_location = it->source_location();
1035+
error() << "static_assert not supported in compound body" << eom;
1036+
throw 0;
1037+
}
1038+
10321039
exprt &assertion = to_binary_expr(*it).op0();
10331040
typecheck_expr(assertion);
10341041
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
}

0 commit comments

Comments
 (0)