Add __attribute__((aligned(N)) for struct declaration

This commit is contained in:
Rui Ueyama 2020-09-25 14:48:38 +09:00
parent 44bea4c85a
commit b35d148a8d
2 changed files with 50 additions and 13 deletions

43
parse.c
View File

@ -2595,25 +2595,44 @@ static void struct_members(Token **rest, Token *tok, Type *ty) {
ty->members = head.next; ty->members = head.next;
} }
// attribute = ("__attribute__" "(" "(" "packed" ")" ")")? // attribute = ("__attribute__" "(" "(" "packed" ")" ")")*
static Token *attribute(Token *tok, Type *ty) { static Token *attribute_list(Token *tok, Type *ty) {
if (!equal(tok, "__attribute__")) while (consume(&tok, tok, "__attribute__")) {
return tok; tok = skip(tok, "(");
tok = skip(tok, "(");
tok = tok->next; bool first = true;
tok = skip(tok, "(");
tok = skip(tok, "("); while (!consume(&tok, tok, ")")) {
tok = skip(tok, "packed"); if (!first)
tok = skip(tok, ")"); tok = skip(tok, ",");
tok = skip(tok, ")"); first = false;
if (consume(&tok, tok, "packed")) {
ty->is_packed = true; 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, ")");
}
return tok; return tok;
} }
// struct-union-decl = attribute? ident? ("{" struct-members)? // struct-union-decl = attribute? ident? ("{" struct-members)?
static Type *struct_union_decl(Token **rest, Token *tok) { static Type *struct_union_decl(Token **rest, Token *tok) {
Type *ty = struct_type(); Type *ty = struct_type();
tok = attribute(tok, ty); tok = attribute_list(tok, ty);
// Read a tag. // Read a tag.
Token *tag = NULL; Token *tag = NULL;
@ -2638,7 +2657,7 @@ static Type *struct_union_decl(Token **rest, Token *tok) {
// Construct a struct object. // Construct a struct object.
struct_members(&tok, tok, ty); struct_members(&tok, tok, ty);
*rest = attribute(tok, ty); *rest = attribute_list(tok, ty);
if (tag) { if (tag) {
// If this is a redefinition, overwrite a previous type. // If this is a redefinition, overwrite a previous type.

View File

@ -16,6 +16,24 @@ int main() {
ASSERT(1, offsetof(struct __attribute__((packed)) T { char a; int b[2]; }, b)); 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(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"); printf("OK\n");
return 0; return 0;
} }