Fix _Alignas

* don't accept _Alignas as type qualifier (after pointer '*').
* accept type-names within _Alignas
* add testcases
This commit is contained in:
Michael Matz 2019-04-08 20:58:49 +02:00
parent fa0ef91a24
commit 38a6aba468
5 changed files with 52 additions and 28 deletions

View File

@ -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:

View File

@ -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;
}

View File

@ -0,0 +1 @@
16 8 4

View File

@ -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

View File

@ -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