Linux-Sparse Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/5] support builtin macros & __has_feature()
@ 2020-06-18 20:47 Luc Van Oostenryck
  2020-06-18 20:47 ` [PATCH 1/5] pre-process: add testcases for __has_feature() & __has_extension() Luc Van Oostenryck
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Luc Van Oostenryck @ 2020-06-18 20:47 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

This series adds:
* support for builtin macros with arguments
* support for __has_feature() & __has_extension()

Luc Van Oostenryck (5):
  pre-process: add testcases for __has_feature() & __has_extension()
  pre-process: rename 'expander' into 'expand_simple'
  pre-process: add support for builtin macros
  pre-process: add support for __has_feature() & __has_extension()
  pre-process: make __has_{attribute,builtin}() true builtin macros

 ident-list.h                          |   6 +-
 lib.c                                 |   2 -
 pre-process.c                         | 180 ++++++++++++++++++--------
 symbol.h                              |   4 +-
 validation/preprocessor/has-feature.c |  20 +++
 5 files changed, 151 insertions(+), 61 deletions(-)
 create mode 100644 validation/preprocessor/has-feature.c

-- 
2.27.0

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/5] pre-process: add testcases for __has_feature() & __has_extension()
  2020-06-18 20:47 [PATCH 0/5] support builtin macros & __has_feature() Luc Van Oostenryck
@ 2020-06-18 20:47 ` Luc Van Oostenryck
  2020-06-18 20:47 ` [PATCH 2/5] pre-process: rename 'expander' into 'expand_simple' Luc Van Oostenryck
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Luc Van Oostenryck @ 2020-06-18 20:47 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

The support for these builtin macros is incoming.
So, add some testcases for them.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 validation/preprocessor/has-feature.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 validation/preprocessor/has-feature.c

diff --git a/validation/preprocessor/has-feature.c b/validation/preprocessor/has-feature.c
new file mode 100644
index 000000000000..3ab7c3e039fa
--- /dev/null
+++ b/validation/preprocessor/has-feature.c
@@ -0,0 +1,21 @@
+#ifndef __has_feature
+__has_feature()??? Quesako?
+#define __has_feature(x) 0
+#else
+"has __has_feature(), yeah!"
+#endif
+
+#if __has_feature(not_a_feature)
+#error "not a feature!"
+#endif
+
+/*
+ * check-name: has-feature
+ * check-command: sparse -E $file
+ * check-known-to-fail
+ *
+ * check-output-start
+
+"has __has_feature(), yeah!"
+ * check-output-end
+ */
-- 
2.27.0

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 2/5] pre-process: rename 'expander' into 'expand_simple'
  2020-06-18 20:47 [PATCH 0/5] support builtin macros & __has_feature() Luc Van Oostenryck
  2020-06-18 20:47 ` [PATCH 1/5] pre-process: add testcases for __has_feature() & __has_extension() Luc Van Oostenryck
@ 2020-06-18 20:47 ` Luc Van Oostenryck
  2020-06-18 20:47 ` [PATCH 3/5] pre-process: add support for builtin macros Luc Van Oostenryck
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Luc Van Oostenryck @ 2020-06-18 20:47 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Sparse support the expansion of one-symbol-builtin macros like
__FILE__ or the pre-processor operator 'defined'. It also supports the
expansion of builtin macros with arguments, like __has_attribute()
but only inside a pre-processor conditional expression.

In preparation of adding the general expansion of these macros,
rename the method 'expander' into 'expand_simple'.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 pre-process.c | 8 ++++----
 symbol.h      | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/pre-process.c b/pre-process.c
index e6becf233eba..059a7c1d9b7b 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -229,8 +229,8 @@ static int expand_one_symbol(struct token **list)
 	sym = lookup_macro(token->ident);
 	if (!sym)
 		return 1;
-	if (sym->expander) {
-		sym->expander(token);
+	if (sym->expand_simple) {
+		sym->expand_simple(token);
 		return 1;
 	} else {
 		int rc;
@@ -2040,7 +2040,7 @@ static void init_preprocessor(void)
 	};
 	static struct {
 		const char *name;
-		void (*expander)(struct token *);
+		void (*expand_simple)(struct token *);
 	} dynamic[] = {
 		{ "__LINE__",		expand_line },
 		{ "__FILE__",		expand_file },
@@ -2066,7 +2066,7 @@ static void init_preprocessor(void)
 	for (i = 0; i < ARRAY_SIZE(dynamic); i++) {
 		struct symbol *sym;
 		sym = create_symbol(stream, dynamic[i].name, SYM_NODE, NS_MACRO);
-		sym->expander = dynamic[i].expander;
+		sym->expand_simple = dynamic[i].expand_simple;
 	}
 
 	counter_macro = 0;
diff --git a/symbol.h b/symbol.h
index a16a27c24afe..6b483101548a 100644
--- a/symbol.h
+++ b/symbol.h
@@ -160,7 +160,7 @@ struct symbol {
 			struct token *expansion;
 			struct token *arglist;
 			struct scope *used_in;
-			void (*expander)(struct token *);
+			void (*expand_simple)(struct token *);
 		};
 		struct /* NS_PREPROCESSOR */ {
 			int (*handler)(struct stream *, struct token **, struct token *);
-- 
2.27.0

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 3/5] pre-process: add support for builtin macros
  2020-06-18 20:47 [PATCH 0/5] support builtin macros & __has_feature() Luc Van Oostenryck
  2020-06-18 20:47 ` [PATCH 1/5] pre-process: add testcases for __has_feature() & __has_extension() Luc Van Oostenryck
  2020-06-18 20:47 ` [PATCH 2/5] pre-process: rename 'expander' into 'expand_simple' Luc Van Oostenryck
@ 2020-06-18 20:47 ` Luc Van Oostenryck
  2020-06-18 20:47 ` [PATCH 4/5] pre-process: add support for __has_feature() & __has_extension() Luc Van Oostenryck
  2020-06-18 20:47 ` [PATCH 5/5] pre-process: make __has_{attribute,builtin}() true builtin macros Luc Van Oostenryck
  4 siblings, 0 replies; 6+ messages in thread
From: Luc Van Oostenryck @ 2020-06-18 20:47 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Sparse support the expansion of one-symbol-builtin macros like __FILE__.
It also support builtin macros with an argument, like 'defined()'
or '__has_attribute()'.

However, these last one are only expanded inside a pre-processor
conditional expression. This is correct for 'defined()' but macros
like '__has_attribute()' should be expanded in all contexts,
like user defined macros.

So, add support for the general expansion of such macros.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 pre-process.c | 34 ++++++++++++++++++++++++++++++++++
 symbol.h      |  2 ++
 2 files changed, 36 insertions(+)

diff --git a/pre-process.c b/pre-process.c
index 059a7c1d9b7b..d2e13400711e 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -777,6 +777,9 @@ static int expand(struct token **list, struct symbol *sym)
 		expand_arguments(nargs, args);
 	}
 
+	if (sym->expand)
+		return sym->expand(token, args) ? 0 : 1;
+
 	expanding->tainted = 1;
 
 	last = token->next;
@@ -2000,6 +2003,34 @@ static int handle_nondirective(struct stream *stream, struct token **line, struc
 	return 1;
 }
 
+static void create_arglist(struct symbol *sym, int count)
+{
+	struct token *token;
+	struct token **next;
+
+	if (!count)
+		return;
+
+	token = __alloc_token(0);
+	token_type(token) = TOKEN_ARG_COUNT;
+	token->count.normal = count;
+	sym->arglist = token;
+	next = &token->next;
+
+	while (count--) {
+		struct token *id, *uses;
+		id = __alloc_token(0);
+		token_type(id) = TOKEN_IDENT;
+		uses = __alloc_token(0);
+		token_type(uses) = TOKEN_ARG_COUNT;
+		uses->count.normal = 1;
+
+		*next = id;
+		id->next = uses;
+		next = &uses->next;
+	}
+	*next = &eof_token_entry;
+}
 
 static void init_preprocessor(void)
 {
@@ -2041,6 +2072,7 @@ static void init_preprocessor(void)
 	static struct {
 		const char *name;
 		void (*expand_simple)(struct token *);
+		bool (*expand)(struct token *, struct arg *args);
 	} dynamic[] = {
 		{ "__LINE__",		expand_line },
 		{ "__FILE__",		expand_file },
@@ -2067,6 +2099,8 @@ static void init_preprocessor(void)
 		struct symbol *sym;
 		sym = create_symbol(stream, dynamic[i].name, SYM_NODE, NS_MACRO);
 		sym->expand_simple = dynamic[i].expand_simple;
+		if ((sym->expand = dynamic[i].expand) != NULL)
+			create_arglist(sym, 1);
 	}
 
 	counter_macro = 0;
diff --git a/symbol.h b/symbol.h
index 6b483101548a..e256322e83a2 100644
--- a/symbol.h
+++ b/symbol.h
@@ -114,6 +114,7 @@ struct decl_state {
 
 struct pseudo;
 struct entrypoint;
+struct arg;
 
 struct symbol_op {
 	enum keyword type;
@@ -161,6 +162,7 @@ struct symbol {
 			struct token *arglist;
 			struct scope *used_in;
 			void (*expand_simple)(struct token *);
+			bool (*expand)(struct token *, struct arg *args);
 		};
 		struct /* NS_PREPROCESSOR */ {
 			int (*handler)(struct stream *, struct token **, struct token *);
-- 
2.27.0

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 4/5] pre-process: add support for __has_feature() & __has_extension()
  2020-06-18 20:47 [PATCH 0/5] support builtin macros & __has_feature() Luc Van Oostenryck
                   ` (2 preceding siblings ...)
  2020-06-18 20:47 ` [PATCH 3/5] pre-process: add support for builtin macros Luc Van Oostenryck
@ 2020-06-18 20:47 ` Luc Van Oostenryck
  2020-06-18 20:47 ` [PATCH 5/5] pre-process: make __has_{attribute,builtin}() true builtin macros Luc Van Oostenryck
  4 siblings, 0 replies; 6+ messages in thread
From: Luc Van Oostenryck @ 2020-06-18 20:47 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Add the trivial methods for the expansion of these macros with:
c_alignas, c_alignof, c_generic_selections and c_static_assert.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 ident-list.h                          |  4 ++
 pre-process.c                         | 54 +++++++++++++++++++++++++++
 validation/preprocessor/has-feature.c |  1 -
 3 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/ident-list.h b/ident-list.h
index 75740b9d9f77..a3a282587c67 100644
--- a/ident-list.h
+++ b/ident-list.h
@@ -61,6 +61,10 @@ IDENT(defined);
 IDENT(once);
 IDENT(__has_attribute);
 IDENT(__has_builtin);
+IDENT(c_alignas);
+IDENT(c_alignof);
+IDENT(c_generic_selections);
+IDENT(c_static_assert);
 __IDENT(pragma_ident, "__pragma__", 0);
 __IDENT(__VA_ARGS___ident, "__VA_ARGS__", 0);
 __IDENT(__func___ident, "__func__", 0);
diff --git a/pre-process.c b/pre-process.c
index d2e13400711e..7a39b1715f31 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -2003,6 +2003,58 @@ static int handle_nondirective(struct stream *stream, struct token **line, struc
 	return 1;
 }
 
+static bool expand_has_extension(struct token *token, struct arg *args)
+{
+	struct token *arg = args[0].expanded;
+	struct ident *ident;
+	bool val = false;
+
+	if (token_type(arg) != TOKEN_IDENT) {
+		sparse_error(arg->pos, "identifier expected");
+		return false;
+	}
+
+	ident = arg->ident;
+	if (ident == &c_alignas_ident)
+		val = true;
+	else if (ident == &c_alignof_ident)
+		val = true;
+	else if (ident == &c_generic_selections_ident)
+		val = true;
+	else if (ident == &c_static_assert_ident)
+		val = true;
+
+	replace_with_bool(token, val);
+	return 1;
+}
+
+static bool expand_has_feature(struct token *token, struct arg *args)
+{
+	struct token *arg = args[0].expanded;
+	struct ident *ident;
+	bool val = false;
+
+	if (token_type(arg) != TOKEN_IDENT) {
+		sparse_error(arg->pos, "identifier expected");
+		return false;
+	}
+
+	ident = arg->ident;
+	if (standard >= STANDARD_C11) {
+		if (ident == &c_alignas_ident)
+			val = true;
+		else if (ident == &c_alignof_ident)
+			val = true;
+		else if (ident == &c_generic_selections_ident)
+			val = true;
+		else if (ident == &c_static_assert_ident)
+			val = true;
+	}
+
+	replace_with_bool(token, val);
+	return 1;
+}
+
 static void create_arglist(struct symbol *sym, int count)
 {
 	struct token *token;
@@ -2081,6 +2133,8 @@ static void init_preprocessor(void)
 		{ "__TIME__",		expand_time },
 		{ "__COUNTER__",	expand_counter },
 		{ "__INCLUDE_LEVEL__",	expand_include_level },
+		{ "__has_extension",	NULL, expand_has_extension },
+		{ "__has_feature",	NULL, expand_has_feature },
 	};
 
 	for (i = 0; i < ARRAY_SIZE(normal); i++) {
diff --git a/validation/preprocessor/has-feature.c b/validation/preprocessor/has-feature.c
index 3ab7c3e039fa..e0f2e7f63cda 100644
--- a/validation/preprocessor/has-feature.c
+++ b/validation/preprocessor/has-feature.c
@@ -12,7 +12,6 @@ __has_feature()??? Quesako?
 /*
  * check-name: has-feature
  * check-command: sparse -E $file
- * check-known-to-fail
  *
  * check-output-start
 
-- 
2.27.0

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 5/5] pre-process: make __has_{attribute,builtin}() true builtin macros
  2020-06-18 20:47 [PATCH 0/5] support builtin macros & __has_feature() Luc Van Oostenryck
                   ` (3 preceding siblings ...)
  2020-06-18 20:47 ` [PATCH 4/5] pre-process: add support for __has_feature() & __has_extension() Luc Van Oostenryck
@ 2020-06-18 20:47 ` Luc Van Oostenryck
  4 siblings, 0 replies; 6+ messages in thread
From: Luc Van Oostenryck @ 2020-06-18 20:47 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

The macros __has_atribute() & __has_builtin() are only expanded
in the context of a preprocessor conditional but they should
be expanded like usual user defined macros.

Fix this by using the new infrastructure for builtin macros.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 ident-list.h  |  2 --
 lib.c         |  2 --
 pre-process.c | 84 ++++++++++++++++++++-------------------------------
 3 files changed, 32 insertions(+), 56 deletions(-)

diff --git a/ident-list.h b/ident-list.h
index a3a282587c67..8049b6940745 100644
--- a/ident-list.h
+++ b/ident-list.h
@@ -59,8 +59,6 @@ IDENT_RESERVED(__label__);
  * sparse. */
 IDENT(defined);
 IDENT(once);
-IDENT(__has_attribute);
-IDENT(__has_builtin);
 IDENT(c_alignas);
 IDENT(c_alignof);
 IDENT(c_generic_selections);
diff --git a/lib.c b/lib.c
index 8f071bfe96ef..7ba758bc537f 100644
--- a/lib.c
+++ b/lib.c
@@ -1452,8 +1452,6 @@ static void create_builtin_stream(void)
 	add_pre_buffer("#add_system \"%s/include\"\n", gcc_base_dir);
 	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 7a39b1715f31..38167802f465 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -160,18 +160,6 @@ static void replace_with_defined(struct token *token)
 	replace_with_bool(token, token_defined(token));
 }
 
-static void replace_with_has_builtin(struct token *token)
-{
-	struct symbol *sym = lookup_symbol(token->ident, NS_SYMBOL);
-	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);
@@ -1609,14 +1597,6 @@ static int expression_value(struct token **where)
 				state = 1;
 				beginning = list;
 				break;
-			} else if (p->ident == &__has_builtin_ident) {
-				state = 4;
-				beginning = list;
-				break;
-			} else if (p->ident == &__has_attribute_ident) {
-				state = 6;
-				beginning = list;
-				break;
 			}
 			if (!expand_one_symbol(list))
 				continue;
@@ -1647,38 +1627,6 @@ static int expression_value(struct token **where)
 				sparse_error(p->pos, "missing ')' after \"defined\"");
 			*list = p->next;
 			continue;
-
-		// __has_builtin(x) or __has_attribute(x)
-		case 4: case 6:
-			if (match_op(p, '(')) {
-				state++;
-			} else {
-				sparse_error(p->pos, "missing '(' after \"__has_%s\"",
-					state == 4 ? "builtin" : "attribute");
-				state = 0;
-			}
-			*beginning = p;
-			break;
-		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_%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 8:
-			state = 0;
-			*list = p->next;
-			continue;
 		}
 		list = &p->next;
 	}
@@ -2003,6 +1951,36 @@ static int handle_nondirective(struct stream *stream, struct token **line, struc
 	return 1;
 }
 
+static bool expand_has_attribute(struct token *token, struct arg *args)
+{
+	struct token *arg = args[0].expanded;
+	struct symbol *sym;
+
+	if (token_type(arg) != TOKEN_IDENT) {
+		sparse_error(arg->pos, "identifier expected");
+		return false;
+	}
+
+	sym = lookup_symbol(arg->ident, NS_KEYWORD);
+	replace_with_bool(token, sym && sym->op && sym->op->attribute);
+	return true;
+}
+
+static bool expand_has_builtin(struct token *token, struct arg *args)
+{
+	struct token *arg = args[0].expanded;
+	struct symbol *sym;
+
+	if (token_type(arg) != TOKEN_IDENT) {
+		sparse_error(arg->pos, "identifier expected");
+		return false;
+	}
+
+	sym = lookup_symbol(arg->ident, NS_SYMBOL);
+	replace_with_bool(token, sym && sym->builtin);
+	return true;
+}
+
 static bool expand_has_extension(struct token *token, struct arg *args)
 {
 	struct token *arg = args[0].expanded;
@@ -2133,6 +2111,8 @@ static void init_preprocessor(void)
 		{ "__TIME__",		expand_time },
 		{ "__COUNTER__",	expand_counter },
 		{ "__INCLUDE_LEVEL__",	expand_include_level },
+		{ "__has_attribute",	NULL, expand_has_attribute },
+		{ "__has_builtin",	NULL, expand_has_builtin },
 		{ "__has_extension",	NULL, expand_has_extension },
 		{ "__has_feature",	NULL, expand_has_feature },
 	};
-- 
2.27.0

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, back to index

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-18 20:47 [PATCH 0/5] support builtin macros & __has_feature() Luc Van Oostenryck
2020-06-18 20:47 ` [PATCH 1/5] pre-process: add testcases for __has_feature() & __has_extension() Luc Van Oostenryck
2020-06-18 20:47 ` [PATCH 2/5] pre-process: rename 'expander' into 'expand_simple' Luc Van Oostenryck
2020-06-18 20:47 ` [PATCH 3/5] pre-process: add support for builtin macros Luc Van Oostenryck
2020-06-18 20:47 ` [PATCH 4/5] pre-process: add support for __has_feature() & __has_extension() Luc Van Oostenryck
2020-06-18 20:47 ` [PATCH 5/5] pre-process: make __has_{attribute,builtin}() true builtin macros Luc Van Oostenryck

Linux-Sparse Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-sparse/0 linux-sparse/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-sparse linux-sparse/ https://lore.kernel.org/linux-sparse \
		linux-sparse@vger.kernel.org
	public-inbox-index linux-sparse

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-sparse


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git