aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/pre-process.c
diff options
Diffstat (limited to 'pre-process.c')
-rw-r--r--pre-process.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/pre-process.c b/pre-process.c
index da4b7acd..bf4b8e76 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -165,6 +165,12 @@ static void replace_with_has_builtin(struct token *token)
replace_with_bool(token, sym && sym->builtin);
}
+static void replace_with_has_attribute(struct token *token)
+{
+ struct symbol *sym = lookup_symbol(token->ident, NS_KEYWORD);
+ replace_with_bool(token, sym && sym->op && sym->op->attribute);
+}
+
static void expand_line(struct token *token)
{
replace_with_integer(token, token->pos.line);
@@ -1592,6 +1598,10 @@ static int expression_value(struct token **where)
state = 4;
beginning = list;
break;
+ } else if (p->ident == &__has_attribute_ident) {
+ state = 6;
+ beginning = list;
+ break;
}
if (!expand_one_symbol(list))
continue;
@@ -1623,29 +1633,34 @@ static int expression_value(struct token **where)
*list = p->next;
continue;
- // __has_builtin(xyz)
- case 4:
+ // __has_builtin(x) or __has_attribute(x)
+ case 4: case 6:
if (match_op(p, '(')) {
- state = 5;
+ state++;
} else {
- sparse_error(p->pos, "missing '(' after \"__has_builtin\"");
+ sparse_error(p->pos, "missing '(' after \"__has_%s\"",
+ state == 4 ? "builtin" : "attribute");
state = 0;
}
*beginning = p;
break;
- case 5:
+ case 5: case 7:
if (token_type(p) != TOKEN_IDENT) {
sparse_error(p->pos, "identifier expected");
state = 0;
break;
}
if (!match_op(p->next, ')'))
- sparse_error(p->pos, "missing ')' after \"__has_builtin\"");
- state = 6;
- replace_with_has_builtin(p);
+ sparse_error(p->pos, "missing ')' after \"__has_%s\"",
+ state == 5 ? "builtin" : "attribute");
+ if (state == 5)
+ replace_with_has_builtin(p);
+ else
+ replace_with_has_attribute(p);
+ state = 8;
*beginning = p;
break;
- case 6:
+ case 8:
state = 0;
*list = p->next;
continue;