aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/parse.c
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2021-01-01 22:21:46 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2021-01-01 22:21:46 +0100
commitfe455dd6b9fb47743271f342691c4b68532f1260 (patch)
tree44e21912adf82caa03e11214fc682bbe460e1b16 /parse.c
parent10283ac0f48df99e02a5cb16a423972ae42de00d (diff)
parent2cf493d1f63f075e6fe0cccbcb7463b1aa773a74 (diff)
downloadsparse-dev-fe455dd6b9fb47743271f342691c4b68532f1260.tar.gz
Merge branch 'packed'
* packed: add support for __packed struct
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c78
1 files changed, 41 insertions, 37 deletions
diff --git a/parse.c b/parse.c
index 0b268570..70be616c 100644
--- a/parse.c
+++ b/parse.c
@@ -669,6 +669,8 @@ struct statement *alloc_statement(struct position pos, int type)
static struct token *struct_declaration_list(struct token *token, struct symbol_list **list);
+static void apply_ctype(struct position pos, struct ctype *dst, struct ctype *src);
+
static void apply_modifiers(struct position pos, struct decl_state *ctx)
{
struct symbol *ctype;
@@ -717,10 +719,11 @@ static struct token *struct_union_enum_specifier(enum type type,
struct token *token, struct decl_state *ctx,
struct token *(*parse)(struct token *, struct symbol *))
{
+ struct decl_state attr = { };
struct symbol *sym;
struct position *repos;
- token = handle_attributes(token, ctx);
+ token = handle_attributes(token, &attr);
if (token_type(token) == TOKEN_IDENT) {
sym = lookup_symbol(token->ident, NS_STRUCT);
if (!sym ||
@@ -736,35 +739,36 @@ static struct token *struct_union_enum_specifier(enum type type,
ctx->ctype.base_type = sym;
repos = &token->pos;
token = token->next;
- if (match_op(token, '{')) {
- // The following test is actually wrong for empty
- // structs, but (1) they are not C99, (2) gcc does
- // the same thing, and (3) it's easier.
- if (sym->symbol_list)
- error_die(token->pos, "redefinition of %s", show_typename (sym));
- sym->pos = *repos;
- token = parse(token->next, sym);
- token = expect(token, '}', "at end of struct-union-enum-specifier");
-
- // Mark the structure as needing re-examination
- sym->examined = 0;
- sym->endpos = token->pos;
- }
- return token;
- }
+ if (!match_op(token, '{'))
+ return token;
- // private struct/union/enum type
- if (!match_op(token, '{')) {
+ // The following test is actually wrong for empty
+ // structs, but (1) they are not C99, (2) gcc does
+ // the same thing, and (3) it's easier.
+ if (sym->symbol_list)
+ error_die(token->pos, "redefinition of %s", show_typename (sym));
+ sym->pos = *repos;
+
+ // Mark the structure as needing re-examination
+ sym->examined = 0;
+ } else if (match_op(token, '{')) {
+ // private struct/union/enum type
+ sym = alloc_symbol(token->pos, type);
+ set_current_scope(sym); // used by dissect
+ ctx->ctype.base_type = sym;
+ } else {
sparse_error(token->pos, "expected declaration");
ctx->ctype.base_type = &bad_ctype;
return token;
}
- sym = alloc_symbol(token->pos, type);
- set_current_scope(sym); // used by dissect
token = parse(token->next, sym);
- ctx->ctype.base_type = sym;
- token = expect(token, '}', "at end of specifier");
+ token = expect(token, '}', "at end of specifier");
+ attr.ctype.base_type = sym;
+ token = handle_attributes(token, &attr);
+ apply_ctype(token->pos, &sym->ctype, &attr.ctype);
+ sym->packed = attr.packed;
+
sym->endpos = token->pos;
return token;
@@ -1043,8 +1047,6 @@ static struct token *enum_specifier(struct token *token, struct symbol *sym, str
return ret;
}
-static void apply_ctype(struct position pos, struct ctype *thistype, struct ctype *ctype);
-
static struct token *typeof_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx)
{
@@ -1056,7 +1058,7 @@ static struct token *typeof_specifier(struct token *token, struct symbol *sym, s
struct symbol *sym;
token = typename(token->next, &sym, NULL);
ctx->ctype.base_type = sym->ctype.base_type;
- apply_ctype(token->pos, &sym->ctype, &ctx->ctype);
+ apply_ctype(token->pos, &ctx->ctype, &sym->ctype);
} else {
struct symbol *typeof_sym = alloc_symbol(token->pos, SYM_TYPEOF);
token = parse_expression(token->next, &typeof_sym->initializer);
@@ -1088,8 +1090,10 @@ static struct token *ignore_attribute(struct token *token, struct symbol *attr,
static struct token *attribute_packed(struct token *token, struct symbol *attr, struct decl_state *ctx)
{
- if (!ctx->ctype.alignment)
+ if (!ctx->ctype.alignment) {
ctx->ctype.alignment = 1;
+ ctx->packed = 1;
+ }
return token;
}
@@ -1427,24 +1431,24 @@ static struct token *generic_qualifier(struct token *next, struct symbol *sym, s
return next;
}
-static void apply_ctype(struct position pos, struct ctype *thistype, struct ctype *ctype)
+static void apply_ctype(struct position pos, struct ctype *dst, struct ctype *src)
{
- unsigned long mod = thistype->modifiers;
+ unsigned long mod = src->modifiers;
if (mod)
- apply_qualifier(&pos, ctype, mod);
+ apply_qualifier(&pos, dst, mod);
/* Context */
- concat_ptr_list((struct ptr_list *)thistype->contexts,
- (struct ptr_list **)&ctype->contexts);
+ concat_ptr_list((struct ptr_list *)src->contexts,
+ (struct ptr_list **)&dst->contexts);
/* Alignment */
- if (thistype->alignment > ctype->alignment)
- ctype->alignment = thistype->alignment;
+ if (src->alignment > dst->alignment)
+ dst->alignment = src->alignment;
/* Address space */
- if (thistype->as)
- ctype->as = thistype->as;
+ if (src->as)
+ dst->as = src->as;
}
static void specifier_conflict(struct position pos, int what, struct ident *new)
@@ -1529,7 +1533,7 @@ static struct token *declaration_specifiers(struct token *token, struct decl_sta
break;
seen |= Set_S | Set_T;
ctx->ctype.base_type = s->ctype.base_type;
- apply_ctype(token->pos, &s->ctype, &ctx->ctype);
+ apply_ctype(token->pos, &ctx->ctype, &s->ctype);
token = token->next;
continue;
}