From 38a6aba4685456192a9e41cd66cd41189ae8de0a Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 8 Apr 2019 20:58:49 +0200 Subject: [PATCH] Fix _Alignas * don't accept _Alignas as type qualifier (after pointer '*'). * accept type-names within _Alignas * add testcases --- tccgen.c | 45 ++++++++-------------- tests/tests2/102_alignas.c | 28 ++++++++++++++ tests/tests2/102_alignas.expect | 1 + tests/tests2/60_errors_and_warnings.c | 3 ++ tests/tests2/60_errors_and_warnings.expect | 3 ++ 5 files changed, 52 insertions(+), 28 deletions(-) create mode 100644 tests/tests2/102_alignas.c create mode 100644 tests/tests2/102_alignas.expect diff --git a/tccgen.c b/tccgen.c index cab801ae..223a1a77 100644 --- a/tccgen.c +++ b/tccgen.c @@ -4176,20 +4176,25 @@ static int parse_btype(CType *type, AttributeDef *ad) goto basic_type; case TOK_ALIGNAS: { int n; - next(); - /* TODO: _Alignas(type) -> _Alignas(_Alignof(type)) */ - if (tok == '(') { - next(); - n = expr_const(); - if (n <= 0 || (n & (n - 1)) != 0) + AttributeDef ad1; + next(); + skip('('); + memset(&ad1, 0, sizeof(AttributeDef)); + if (parse_btype(&type1, &ad1)) { + type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); + if (ad1.a.aligned) + n = 1 << (ad1.a.aligned - 1); + else + type_size(&type1, &n); + } else { + n = expr_const(); + if (n <= 0 || (n & (n - 1)) != 0) tcc_error("alignment must be a positive power of two"); - skip(')'); - } else { - expect("("); + } + skip(')'); + ad->a.aligned = exact_log2p1(n); } - ad->a.aligned = exact_log2p1(n); - } - continue; + continue; case TOK_LONG: if ((t & VT_BTYPE) == VT_DOUBLE) { t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LDOUBLE; @@ -4594,22 +4599,6 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td) case TOK_RESTRICT2: case TOK_RESTRICT3: goto redo; - case TOK_ALIGNAS: - { int n; - next(); - /* TODO: _Alignas(type) -> _Alignas(_Alignof(type)) */ - if (tok == '(') { - next(); - n = expr_const(); - if (n <= 0 || (n & (n - 1)) != 0) - tcc_error("alignment must be a positive power of two"); - skip(')'); - } else { - expect("("); - } - ad->a.aligned = exact_log2p1(n); - } - break; /* XXX: clarify attribute handling */ case TOK_ATTRIBUTE1: case TOK_ATTRIBUTE2: diff --git a/tests/tests2/102_alignas.c b/tests/tests2/102_alignas.c new file mode 100644 index 00000000..57a38b29 --- /dev/null +++ b/tests/tests2/102_alignas.c @@ -0,0 +1,28 @@ +_Alignas(16) int i1; +int _Alignas(16) i2; +void _Alignas(16) *p2; +_Alignas(16) i3; +int _Alignas(double) i4; +int _Alignas(int) i5; +#if 0 +/* The following are currently wrongly accepted by TCC but really shouldn't. */ +int _Alignas(int _Alignas(16)) i6; //wrong, 'int _Alignas(16)' is no type-name +typedef int _Alignas(16) int16aligned_t; //wrong, _Alignas invalid on typedef +int16aligned_t i7; +#endif +/* i8 should get an alignment of 16, because unlike _Alignas the + corresponding attribute _does_ apply to type-name, though not in + some clang versions. */ +int _Alignas(int __attribute__((aligned(16)))) i8; +extern int printf(const char*, ...); +#ifdef _MSC_VER +#define alignof(x) (int)__alignof(x) +#else +#define alignof(x) (int)__alignof__(x) +#endif +int main() +{ + printf("%d %d %d %d\n", + alignof(i1), alignof(i4), alignof(i5), alignof(i8)); + return 0; +} diff --git a/tests/tests2/102_alignas.expect b/tests/tests2/102_alignas.expect new file mode 100644 index 00000000..807063bf --- /dev/null +++ b/tests/tests2/102_alignas.expect @@ -0,0 +1 @@ +16 8 4 diff --git a/tests/tests2/60_errors_and_warnings.c b/tests/tests2/60_errors_and_warnings.c index 61561b8e..90a245bc 100644 --- a/tests/tests2/60_errors_and_warnings.c +++ b/tests/tests2/60_errors_and_warnings.c @@ -172,4 +172,7 @@ int X=1; int main(void) { int t[][][X]; } +#elif defined test_invalid_alignas +/* _Alignas is no type qualifier */ +void * _Alignas(16) p1; #endif diff --git a/tests/tests2/60_errors_and_warnings.expect b/tests/tests2/60_errors_and_warnings.expect index e4ddd9de..99898857 100644 --- a/tests/tests2/60_errors_and_warnings.expect +++ b/tests/tests2/60_errors_and_warnings.expect @@ -80,3 +80,6 @@ [test_vla_1] 60_errors_and_warnings.c:173: error: need explicit inner array size in VLAs + +[test_invalid_alignas] +60_errors_and_warnings.c:177: error: identifier expected