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 | 4207 | /* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */ |
| 4206 | 4208 | static void struct_decl(CType *type, int u) |
| 4207 | 4209 | { |
| @@ -4311,6 +4313,10 @@ do_decl: · 103 unmodified lines | ||
| 4311 | 4313 | c = 0; |
| 4312 | 4314 | flexible = 0; |
| 4313 | 4315 | while (tok != '}') { |
| 4316 | + if (tok == TOK_STATIC_ASSERT) { | |
| 4317 | + do_Static_assert(); | |
| 4318 | + continue; | |
| 4319 | + } | |
| 4314 | 4320 | if (!parse_btype(&btype, &ad1, 0)) { |
| 4315 | 4321 | skip(';'); |
| 4316 | 4322 | continue; |
| @@ -8243,6 +8249,31 @@ static void free_inline_functions(TCCState *s) · 3926 unmodified lines | ||
| 8243 | 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 | 8277 | /* 'l' is VT_LOCAL or VT_CONST to define default storage type |
| 8247 | 8278 | or VT_CMP if parsing old style parameter list |
| 8248 | 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 | 8285 | AttributeDef ad, adbase; |
| 8255 | 8286 | |
| 8256 | 8287 | while (1) { |
| 8257 | − if (tok == TOK_STATIC_ASSERT) { | |
| 8258 | − CString error_str; | |
| 8259 | − int c; | |
| 8260 | − | |
| 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 | − } | |
| 8288 | + if (tok == TOK_STATIC_ASSERT) { | |
| 8289 | + do_Static_assert(); | |
| 8290 | + continue; | |
| 8291 | + } | |
| 8282 | 8292 | |
| 8283 | 8293 | oldint = 0; |
| 8284 | 8294 | if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) { |
| @@ -191,15 +191,15 @@ void * _Alignas(16) p1; · 190 unmodified lines | ||
| 191 | 191 | |
| 192 | 192 | #define ONE 0 |
| 193 | 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 | 196 | #elif defined test_static_assert_2 |
| 197 | 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 | 200 | #elif defined test_static_assert_c2x |
| 201 | 201 | _Static_assert(1); |
| 202 | − _Static_assert(0); | |
| 202 | +struct z { _Static_assert(0); } | |
| 203 | 203 | |
| 204 | 204 | #elif defined test_static_assert_empty_string |
| 205 | 205 | _Static_assert(0,""); |