Allow _Static_assert declarations in structs

This usage has been part of the C grammar since C11
(http://port70.net/~nsz/c/c11/n1570.html#6.7.2.1) and is
also supported by gcc and clang.
This commit is contained in:
Petr Skocik 2022-12-10 01:12:44 +01:00
parent ac9eeea1d5
commit ea0c57e90a
2 changed files with 38 additions and 28 deletions

View File

@ -4202,6 +4202,8 @@ static void struct_layout(CType *type, AttributeDef *ad)
}
}
static void do_Static_assert(void);
/* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */
static void struct_decl(CType *type, int u)
{
@ -4311,6 +4313,10 @@ do_decl:
c = 0;
flexible = 0;
while (tok != '}') {
if (tok == TOK_STATIC_ASSERT) {
do_Static_assert();
continue;
}
if (!parse_btype(&btype, &ad1, 0)) {
skip(';');
continue;
@ -8243,6 +8249,31 @@ static void free_inline_functions(TCCState *s)
dynarray_reset(&s->inline_fns, &s->nb_inline_fns);
}
static void do_Static_assert(void){
CString error_str;
int c;
next();
skip('(');
c = expr_const();
if (tok == ')') {
if (!c)
tcc_error("_Static_assert fail");
next();
goto static_assert_out;
}
skip(',');
parse_mult_str(&error_str, "string constant");
if (c == 0)
tcc_error("%s", (char *)error_str.data);
cstr_free(&error_str);
skip(')');
static_assert_out:
skip(';');
}
/* 'l' is VT_LOCAL or VT_CONST to define default storage type
or VT_CMP if parsing old style parameter list
or VT_JMP if parsing c99 for decl: for (int i = 0, ...) */
@ -8254,31 +8285,10 @@ static int decl(int l)
AttributeDef ad, adbase;
while (1) {
if (tok == TOK_STATIC_ASSERT) {
CString error_str;
int c;
next();
skip('(');
c = expr_const();
if (tok == ')') {
if (!c)
tcc_error("_Static_assert fail");
next();
goto static_assert_out;
}
skip(',');
parse_mult_str(&error_str, "string constant");
if (c == 0)
tcc_error("%s", (char *)error_str.data);
cstr_free(&error_str);
skip(')');
static_assert_out:
skip(';');
continue;
}
if (tok == TOK_STATIC_ASSERT) {
do_Static_assert();
continue;
}
oldint = 0;
if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) {

View File

@ -191,15 +191,15 @@ void * _Alignas(16) p1;
#define ONE 0
_Static_assert(ONE == 0, "don't show me this");
_Static_assert(ONE == 1, "ONE is not 1");
struct x{ _Static_assert(ONE == 1, "ONE is not 1"); };
#elif defined test_static_assert_2
_Static_assert(1, "1"" is 1");
_Static_assert(0, "0"" is 0");
struct y { _Static_assert(0, "0"" is 0"); };
#elif defined test_static_assert_c2x
_Static_assert(1);
_Static_assert(0);
struct z { _Static_assert(0); }
#elif defined test_static_assert_empty_string
_Static_assert(0,"");