[PATCH 4/4] has-attr: add support for __has_attribute()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Sparse has support for a subset of GCC's large collection of
attributes. It's not easy to know wich versions support this
or this attributes but since GCC5, there is a good solution
to this problem: the magic macro __has_attribute(<name>)
which evaluates to 1 if <name> is an attribute known to the
compiler and 0 otherwise.

Add support for this __has_attribute() macro by extending the
already existing support for __has_builtin().

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx>
---
 ident-list.h                            |  1 +
 lib.c                                   |  1 +
 pre-process.c                           | 33 ++++++++++++++++++-------
 validation/preprocessor/has-attribute.c |  1 -
 4 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/ident-list.h b/ident-list.h
index a37a4a1b5..75740b9d9 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 db456a63e..48c6dc983 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/pre-process.c b/pre-process.c
index da4b7acdb..bf4b8e766 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
index ec8dbb06e..3149cbfa6 100644
--- a/validation/preprocessor/has-attribute.c
+++ b/validation/preprocessor/has-attribute.c
@@ -44,7 +44,6 @@ __has_attribute()??? Quesako?
 /*
  * check-name: has-attribute
  * check-command: sparse -E $file
- * check-known-to-fail
  *
  * check-output-start
 
-- 
2.18.0




[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux