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:
parent
ac9eeea1d5
commit
ea0c57e90a
2 changed files with 38 additions and 28 deletions
60
tccgen.c
60
tccgen.c
|
@ -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 */
|
/* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */
|
||||||
static void struct_decl(CType *type, int u)
|
static void struct_decl(CType *type, int u)
|
||||||
{
|
{
|
||||||
|
@ -4311,6 +4313,10 @@ do_decl:
|
||||||
c = 0;
|
c = 0;
|
||||||
flexible = 0;
|
flexible = 0;
|
||||||
while (tok != '}') {
|
while (tok != '}') {
|
||||||
|
if (tok == TOK_STATIC_ASSERT) {
|
||||||
|
do_Static_assert();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!parse_btype(&btype, &ad1, 0)) {
|
if (!parse_btype(&btype, &ad1, 0)) {
|
||||||
skip(';');
|
skip(';');
|
||||||
continue;
|
continue;
|
||||||
|
@ -8243,6 +8249,31 @@ static void free_inline_functions(TCCState *s)
|
||||||
dynarray_reset(&s->inline_fns, &s->nb_inline_fns);
|
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
|
/* 'l' is VT_LOCAL or VT_CONST to define default storage type
|
||||||
or VT_CMP if parsing old style parameter list
|
or VT_CMP if parsing old style parameter list
|
||||||
or VT_JMP if parsing c99 for decl: for (int i = 0, ...) */
|
or VT_JMP if parsing c99 for decl: for (int i = 0, ...) */
|
||||||
|
@ -8254,31 +8285,10 @@ static int decl(int l)
|
||||||
AttributeDef ad, adbase;
|
AttributeDef ad, adbase;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (tok == TOK_STATIC_ASSERT) {
|
if (tok == TOK_STATIC_ASSERT) {
|
||||||
CString error_str;
|
do_Static_assert();
|
||||||
int c;
|
continue;
|
||||||
|
}
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
oldint = 0;
|
oldint = 0;
|
||||||
if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) {
|
if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) {
|
||||||
|
|
|
@ -191,15 +191,15 @@ void * _Alignas(16) p1;
|
||||||
|
|
||||||
#define ONE 0
|
#define ONE 0
|
||||||
_Static_assert(ONE == 0, "don't show me this");
|
_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
|
#elif defined test_static_assert_2
|
||||||
_Static_assert(1, "1"" is 1");
|
_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
|
#elif defined test_static_assert_c2x
|
||||||
_Static_assert(1);
|
_Static_assert(1);
|
||||||
_Static_assert(0);
|
struct z { _Static_assert(0); }
|
||||||
|
|
||||||
#elif defined test_static_assert_empty_string
|
#elif defined test_static_assert_empty_string
|
||||||
_Static_assert(0,"");
|
_Static_assert(0,"");
|
||||||
|
|
Loading…
Reference in a new issue