aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
-rw-r--r--ident-list.h1
-rw-r--r--lib.c1
-rw-r--r--parse.c4
-rw-r--r--pre-process.c33
-rw-r--r--validation/preprocessor/has-attribute.c56
5 files changed, 85 insertions, 10 deletions
diff --git a/ident-list.h b/ident-list.h
index a37a4a1b..75740b9d 100644
--- a/ident-list.h
+++ b/ident-list.h
@@ -59,6 +59,7 @@ IDENT_RESERVED(__label__);
* sparse. */
IDENT(defined);
IDENT(once);
+IDENT(__has_attribute);
IDENT(__has_builtin);
__IDENT(pragma_ident, "__pragma__", 0);
__IDENT(__VA_ARGS___ident, "__VA_ARGS__", 0);
diff --git a/lib.c b/lib.c
index db456a63..48c6dc98 100644
--- a/lib.c
+++ b/lib.c
@@ -1287,6 +1287,7 @@ static void create_builtin_stream(void)
add_pre_buffer("#add_system \"%s/include-fixed\"\n", gcc_base_dir);
add_pre_buffer("#define __has_builtin(x) 0\n");
+ add_pre_buffer("#define __has_attribute(x) 0\n");
add_pre_buffer("#define __builtin_stdarg_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
add_pre_buffer("#define __builtin_va_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
add_pre_buffer("#define __builtin_ms_va_start(a,b) ((a) = (__builtin_ms_va_list)(&(b)))\n");
diff --git a/parse.c b/parse.c
index fb63ca2e..00b8ebbd 100644
--- a/parse.c
+++ b/parse.c
@@ -531,9 +531,10 @@ static struct init_keyword {
{ "bitwise", NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op },
{ "__bitwise__",NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op },
{ "address_space",NS_KEYWORD, .op = &address_space_op },
- { "mode", NS_KEYWORD, .op = &mode_op },
{ "context", NS_KEYWORD, .op = &context_op },
{ "designated_init", NS_KEYWORD, .op = &designated_init_op },
+ { "__designated_init__", NS_KEYWORD, .op = &designated_init_op },
+ { "transparent_union", NS_KEYWORD, .op = &transparent_union_op },
{ "__transparent_union__", NS_KEYWORD, .op = &transparent_union_op },
{ "noreturn", NS_KEYWORD, MOD_NORETURN, .op = &attr_mod_op },
{ "__noreturn__", NS_KEYWORD, MOD_NORETURN, .op = &attr_mod_op },
@@ -543,6 +544,7 @@ static struct init_keyword {
{"__const", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op },
{"__const__", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op },
+ { "mode", NS_KEYWORD, .op = &mode_op },
{ "__mode__", NS_KEYWORD, .op = &mode_op },
{ "QI", NS_KEYWORD, .op = &mode_QI_op },
{ "__QI__", NS_KEYWORD, .op = &mode_QI_op },
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;
diff --git a/validation/preprocessor/has-attribute.c b/validation/preprocessor/has-attribute.c
new file mode 100644
index 00000000..3149cbfa
--- /dev/null
+++ b/validation/preprocessor/has-attribute.c
@@ -0,0 +1,56 @@
+#ifndef __has_attribute
+__has_attribute()??? Quesako?
+#define __has_attribute(x) 0
+#else
+"has __has_attribute(), yeah!"
+#endif
+
+123 __has_attribute(nothinx) def
+
+#if __has_attribute(nothinx)
+#error "not a attribute!"
+#endif
+
+#if 1 \
+ && __has_attribute(packed) \
+ && __has_attribute(aligned) \
+ && __has_attribute(const) \
+ && __has_attribute(pure) \
+ && __has_attribute(noreturn) \
+ && __has_attribute(designated_init) \
+ && __has_attribute(transparent_union) \
+
+"ok gcc"
+#endif
+
+#if 1 \
+ && __has_attribute(fastcall) \
+
+"ok gcc ignore"
+#endif
+
+#if 1 \
+ && __has_attribute(nocast) \
+ && __has_attribute(noderef) \
+ && __has_attribute(safe) \
+ && __has_attribute(force) \
+ && __has_attribute(bitwise) \
+ && __has_attribute(address_space) \
+ && __has_attribute(context) \
+
+"ok sparse specific"
+#endif
+
+/*
+ * check-name: has-attribute
+ * check-command: sparse -E $file
+ *
+ * check-output-start
+
+"has __has_attribute(), yeah!"
+123 0 def
+"ok gcc"
+"ok gcc ignore"
+"ok sparse specific"
+ * check-output-end
+ */