diff --git a/parse.c b/parse.c index 825e91a..6acaeb8 100644 --- a/parse.c +++ b/parse.c @@ -2595,25 +2595,44 @@ static void struct_members(Token **rest, Token *tok, Type *ty) { ty->members = head.next; } -// attribute = ("__attribute__" "(" "(" "packed" ")" ")")? -static Token *attribute(Token *tok, Type *ty) { - if (!equal(tok, "__attribute__")) - return tok; +// attribute = ("__attribute__" "(" "(" "packed" ")" ")")* +static Token *attribute_list(Token *tok, Type *ty) { + while (consume(&tok, tok, "__attribute__")) { + tok = skip(tok, "("); + tok = skip(tok, "("); + + bool first = true; + + while (!consume(&tok, tok, ")")) { + if (!first) + tok = skip(tok, ","); + first = false; + + if (consume(&tok, tok, "packed")) { + ty->is_packed = true; + continue; + } + + if (consume(&tok, tok, "aligned")) { + tok = skip(tok, "("); + ty->align = const_expr(&tok, tok); + tok = skip(tok, ")"); + continue; + } + + error_tok(tok, "unknown attribute"); + } + + tok = skip(tok, ")"); + } - tok = tok->next; - tok = skip(tok, "("); - tok = skip(tok, "("); - tok = skip(tok, "packed"); - tok = skip(tok, ")"); - tok = skip(tok, ")"); - ty->is_packed = true; return tok; } // struct-union-decl = attribute? ident? ("{" struct-members)? static Type *struct_union_decl(Token **rest, Token *tok) { Type *ty = struct_type(); - tok = attribute(tok, ty); + tok = attribute_list(tok, ty); // Read a tag. Token *tag = NULL; @@ -2638,7 +2657,7 @@ static Type *struct_union_decl(Token **rest, Token *tok) { // Construct a struct object. struct_members(&tok, tok, ty); - *rest = attribute(tok, ty); + *rest = attribute_list(tok, ty); if (tag) { // If this is a redefinition, overwrite a previous type. diff --git a/test/attribute.c b/test/attribute.c index a9adf39..9195d3b 100644 --- a/test/attribute.c +++ b/test/attribute.c @@ -16,6 +16,24 @@ int main() { ASSERT(1, offsetof(struct __attribute__((packed)) T { char a; int b[2]; }, b)); ASSERT(1, _Alignof(struct __attribute__((packed)) { char a; int b[2]; })); + ASSERT(8, ({ struct __attribute__((aligned(8))) { int a; } x; _Alignof(x); })); + ASSERT(8, ({ struct { int a; } __attribute__((aligned(8))) x; _Alignof(x); })); + + ASSERT(8, ({ struct __attribute__((aligned(8), packed)) { char a; int b; } x; _Alignof(x); })); + ASSERT(8, ({ struct { char a; int b; } __attribute__((aligned(8), packed)) x; _Alignof(x); })); + ASSERT(1, offsetof(struct __attribute__((aligned(8), packed)) { char a; int b; }, b)); + ASSERT(1, offsetof(struct { char a; int b; } __attribute__((aligned(8), packed)), b)); + + ASSERT(8, ({ struct __attribute__((aligned(8))) __attribute__((packed)) { char a; int b; } x; _Alignof(x); })); + ASSERT(8, ({ struct { char a; int b; } __attribute__((aligned(8))) __attribute__((packed)) x; _Alignof(x); })); + ASSERT(1, offsetof(struct __attribute__((aligned(8))) __attribute__((packed)) { char a; int b; }, b)); + ASSERT(1, offsetof(struct { char a; int b; } __attribute__((aligned(8))) __attribute__((packed)), b)); + + ASSERT(8, ({ struct __attribute__((aligned(8))) { char a; int b; } __attribute__((packed)) x; _Alignof(x); })); + ASSERT(1, offsetof(struct __attribute__((aligned(8))) { char a; int b; } __attribute__((packed)), b)); + + ASSERT(16, ({ struct __attribute__((aligned(8+8))) { char a; int b; } x; _Alignof(x); })); + printf("OK\n"); return 0; }