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.
Unified · Split
| @@ -4202,6 +4202,8 @@ static void struct_layout(CType *type, AttributeDef *ad) · 4201 unmodified lines | |||
| 4202 | } | 4202 | } |
| 4203 | } | 4203 | } |
| 4204 | 4204 | ||
| 4205 | static void do_Static_assert(void); | ||
| 4206 | |||
| 4205 | /* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */ | 4207 | /* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */ |
| 4206 | static void struct_decl(CType *type, int u) | 4208 | static void struct_decl(CType *type, int u) |
| 4207 | { | 4209 | { |
| @@ -4311,6 +4313,10 @@ do_decl: · 103 unmodified lines | |||
| 4311 | c = 0; | 4313 | c = 0; |
| 4312 | flexible = 0; | 4314 | flexible = 0; |
| 4313 | while (tok != '}') { | 4315 | while (tok != '}') { |
| 4316 | if (tok == TOK_STATIC_ASSERT) { | ||
| 4317 | do_Static_assert(); | ||
| 4318 | continue; | ||
| 4319 | } | ||
| 4314 | if (!parse_btype(&btype, &ad1, 0)) { | 4320 | if (!parse_btype(&btype, &ad1, 0)) { |
| 4315 | skip(';'); | 4321 | skip(';'); |
| 4316 | continue; | 4322 | continue; |
| @@ -8243,6 +8249,31 @@ static void free_inline_functions(TCCState *s) · 3926 unmodified lines | |||
| 8243 | dynarray_reset(&s->inline_fns, &s->nb_inline_fns); | 8249 | dynarray_reset(&s->inline_fns, &s->nb_inline_fns); |
| 8244 | } | 8250 | } |
| 8245 | 8251 | ||
| 8252 | static void do_Static_assert(void){ | ||
| 8253 | CString error_str; | ||
| 8254 | int c; | ||
| 8255 | |||
| 8256 | next(); | ||
| 8257 | skip('('); | ||
| 8258 | c = expr_const(); | ||
| 8259 | |||
| 8260 | if (tok == ')') { | ||
| 8261 | if (!c) | ||
| 8262 | tcc_error("_Static_assert fail"); | ||
| 8263 | next(); | ||
| 8264 | goto static_assert_out; | ||
| 8265 | } | ||
| 8266 | |||
| 8267 | skip(','); | ||
| 8268 | parse_mult_str(&error_str, "string constant"); | ||
| 8269 | if (c == 0) | ||
| 8270 | tcc_error("%s", (char *)error_str.data); | ||
| 8271 | cstr_free(&error_str); | ||
| 8272 | skip(')'); | ||
| 8273 | static_assert_out: | ||
| 8274 | skip(';'); | ||
| 8275 | } | ||
| 8276 | |||
| 8246 | /* 'l' is VT_LOCAL or VT_CONST to define default storage type | 8277 | /* 'l' is VT_LOCAL or VT_CONST to define default storage type |
| 8247 | or VT_CMP if parsing old style parameter list | 8278 | or VT_CMP if parsing old style parameter list |
| 8248 | or VT_JMP if parsing c99 for decl: for (int i = 0, ...) */ | 8279 | or VT_JMP if parsing c99 for decl: for (int i = 0, ...) */ |
| @@ -8254,31 +8285,10 @@ static int decl(int l) · 5 unmodified lines | |||
| 8254 | AttributeDef ad, adbase; | 8285 | AttributeDef ad, adbase; |
| 8255 | 8286 | ||
| 8256 | while (1) { | 8287 | while (1) { |
| 8257 | if (tok == TOK_STATIC_ASSERT) { | 8288 | if (tok == TOK_STATIC_ASSERT) { |
| 8258 | CString error_str; | 8289 | do_Static_assert(); |
| 8259 | int c; | 8290 | continue; |
| 8260 | 8291 | } | |
| 8261 | next(); | ||
| 8262 | skip('('); | ||
| 8263 | c = expr_const(); | ||
| 8264 | |||
| 8265 | if (tok == ')') { | ||
| 8266 | if (!c) | ||
| 8267 | tcc_error("_Static_assert fail"); | ||
| 8268 | next(); | ||
| 8269 | goto static_assert_out; | ||
| 8270 | } | ||
| 8271 | |||
| 8272 | skip(','); | ||
| 8273 | parse_mult_str(&error_str, "string constant"); | ||
| 8274 | if (c == 0) | ||
| 8275 | tcc_error("%s", (char *)error_str.data); | ||
| 8276 | cstr_free(&error_str); | ||
| 8277 | skip(')'); | ||
| 8278 | static_assert_out: | ||
| 8279 | skip(';'); | ||
| 8280 | continue; | ||
| 8281 | } | ||
| 8282 | 8292 | ||
| 8283 | oldint = 0; | 8293 | oldint = 0; |
| 8284 | if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) { | 8294 | if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) { |
| @@ -191,15 +191,15 @@ void * _Alignas(16) p1; · 190 unmodified lines | |||
| 191 | 191 | ||
| 192 | #define ONE 0 | 192 | #define ONE 0 |
| 193 | _Static_assert(ONE == 0, "don't show me this"); | 193 | _Static_assert(ONE == 0, "don't show me this"); |
| 194 | _Static_assert(ONE == 1, "ONE is not 1"); | 194 | struct x{ _Static_assert(ONE == 1, "ONE is not 1"); }; |
| 195 | 195 | ||
| 196 | #elif defined test_static_assert_2 | 196 | #elif defined test_static_assert_2 |
| 197 | _Static_assert(1, "1"" is 1"); | 197 | _Static_assert(1, "1"" is 1"); |
| 198 | _Static_assert(0, "0"" is 0"); | 198 | struct y { _Static_assert(0, "0"" is 0"); }; |
| 199 | 199 | ||
| 200 | #elif defined test_static_assert_c2x | 200 | #elif defined test_static_assert_c2x |
| 201 | _Static_assert(1); | 201 | _Static_assert(1); |
| 202 | _Static_assert(0); | 202 | struct z { _Static_assert(0); } |
| 203 | 203 | ||
| 204 | #elif defined test_static_assert_empty_string | 204 | #elif defined test_static_assert_empty_string |
| 205 | _Static_assert(0,""); | 205 | _Static_assert(0,""); |