aboutsummaryrefslogtreecommitdiff
path: root/decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'decl.c')
-rw-r--r--decl.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/decl.c b/decl.c
index 975a8d5..6e0ee37 100644
--- a/decl.c
+++ b/decl.c
@@ -170,6 +170,7 @@ tagspec(struct scope *s)
default: fatal("internal error: unknown tag kind");
}
next();
+ attr(NULL, 0);
tag = NULL;
t = NULL;
et = NULL;
@@ -236,6 +237,7 @@ tagspec(struct scope *s)
for (value = 0; tok.kind == TIDENT; ++value) {
name = tok.lit;
next();
+ attr(NULL, 0);
if (consume(TASSIGN)) {
e = evalexpr(s);
if (e->kind != EXPRCONST || !(e->type->prop & PROPINT))
@@ -497,6 +499,12 @@ done:
t = mkarraytype(t->base, t->qual | tq, t->u.array.length);
tq = QUALNONE;
}
+ /*
+ TODO: consider delaying attribute parsing to declarator(),
+ so we can tell the difference between the start of an
+ attribute and an array declarator.
+ */
+ attr(NULL, 0);
return (struct qualtype){t, tq};
}
@@ -528,8 +536,10 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs
struct expr *e;
unsigned long long i;
enum typequal tq;
+ bool allowattr;
while (consume(TMUL)) {
+ attr(NULL, 0);
tq = QUALNONE;
while (typequal(&tq))
;
@@ -552,21 +562,25 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs
break;
/* fallthrough */
default:
+ allowattr = true;
goto func;
}
}
declaratortypes(s, result, name, allowabstract);
expect(TRPAREN, "after parenthesized declarator");
+ allowattr = false;
break;
case TIDENT:
if (!name)
error(&tok.loc, "identifier not allowed in abstract declarator");
*name = tok.lit;
next();
+ allowattr = true;
break;
default:
if (!allowabstract)
error(&tok.loc, "expected '(' or identifier");
+ allowattr = true;
}
for (;;) {
switch (tok.kind) {
@@ -615,8 +629,11 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs
expect(TRPAREN, "to close function declarator");
t->u.func.paraminfo = t->u.func.isprototype || t->u.func.params || tok.kind == TLBRACE;
listinsert(ptr->prev, &t->link);
+ allowattr = true;
break;
case TLBRACK: /* array declarator */
+ if (allowattr && attr(NULL, 0))
+ goto attr;
next();
tq = QUALNONE;
while (consume(TSTATIC) || typequal(&tq))
@@ -637,6 +654,14 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs
}
expect(TRBRACK, "after array length");
listinsert(ptr->prev, &t->link);
+ allowattr = true;
+ break;
+ case T__ATTRIBUTE__:
+ if (!allowattr)
+ error(&tok.loc, "attribute not allowed after parenthesized declarator");
+ /* attribute applies to identifier if ptr->prev == result, otherwise type ptr->prev */
+ attr(NULL, 0);
+ attr:
break;
default:
return;
@@ -688,6 +713,7 @@ parameter(struct scope *s)
struct qualtype t;
enum storageclass sc;
+ attr(NULL, 0);
t = declspecs(s, &sc, NULL, NULL);
if (!t.type)
error(&tok.loc, "no type in parameter declaration");
@@ -844,6 +870,7 @@ structdecl(struct scope *s, struct structbuilder *b)
if (staticassert(s))
return;
+ attr(NULL, 0);
base = declspecs(s, NULL, NULL, &align);
if (!base.type)
error(&tok.loc, "no type in struct member declaration");
@@ -966,6 +993,8 @@ decl(struct scope *s, struct func *f)
if (staticassert(s))
return true;
+ if (attr(NULL, 0) && consume(TSEMICOLON))
+ return true;
base = declspecs(s, &sc, &fs, &align);
if (!base.type)
return false;