[PATCH 07/21] make expand_has_...() responsible for expanding its argument

Al Viro <[email protected]> Mon, 16 Mar 2026 07:04:01 +0000
Newsgroups org.kernel.vger.linux-sparse
Message-ID <[email protected]>
If we want to make expansion of arguments on-demand, we need to adjust
->expand() calling conventions first, passing it unexpanded arguments.
Switch create_arglist() to setting argcounts from normal=1 to quoted=1,
provide a helper (first_arg()) that does actual expansion and make
->expand() instances use it.  After that these fake arglists are used
only for two things: they indicate that these macros are function-like
and they short-circuit expand_arguments().  Once we switch to on-demand
argument expansion, the second role will disappear and we can just use
&eof_token_entry as ->arglist for those.

Signed-off-by: Al Viro <[email protected]>
---
 pre-process.c                           | 17 ++++++++++++-----
 validation/preprocessor/has-attribute.c |  3 +++
 validation/preprocessor/has-builtin.c   |  3 +++
 3 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/pre-process.c b/pre-process.c
index 17ed7f85..85662365 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -2000,9 +2000,16 @@ static int handle_nondirective(struct stream *stream, struct token **line, struc
 	return 1;
 }
 
+static struct token *first_arg(struct arg *args)
+{
+	struct token *arg = args[0].arg;
+	expand_list(&arg);
+	return arg;
+}
+
 static bool expand_has_attribute(struct token *token, struct arg *args)
 {
-	struct token *arg = args[0].expanded;
+	struct token *arg = first_arg(args);
 	struct symbol *sym;
 
 	if (token_type(arg) != TOKEN_IDENT) {
@@ -2017,7 +2024,7 @@ static bool expand_has_attribute(struct token *token, struct arg *args)
 
 static bool expand_has_builtin(struct token *token, struct arg *args)
 {
-	struct token *arg = args[0].expanded;
+	struct token *arg = first_arg(args);
 	struct symbol *sym;
 
 	if (token_type(arg) != TOKEN_IDENT) {
@@ -2032,7 +2039,7 @@ static bool expand_has_builtin(struct token *token, struct arg *args)
 
 static bool expand_has_extension(struct token *token, struct arg *args)
 {
-	struct token *arg = args[0].expanded;
+	struct token *arg = first_arg(args);
 	struct ident *ident;
 	bool val = false;
 
@@ -2057,7 +2064,7 @@ static bool expand_has_extension(struct token *token, struct arg *args)
 
 static bool expand_has_feature(struct token *token, struct arg *args)
 {
-	struct token *arg = args[0].expanded;
+	struct token *arg = first_arg(args);
 	struct ident *ident;
 	bool val = false;
 
@@ -2103,7 +2110,7 @@ static void create_arglist(struct symbol *sym, int count)
 		token_type(id) = TOKEN_IDENT;
 		uses = __alloc_token(0);
 		token_type(uses) = TOKEN_ARG_COUNT;
-		uses->count.normal = 1;
+		uses->count.quoted = 1;
 
 		*next = id;
 		id->next = uses;
diff --git a/validation/preprocessor/has-attribute.c b/validation/preprocessor/has-attribute.c
index 3149cbfa..dd0f275e 100644
--- a/validation/preprocessor/has-attribute.c
+++ b/validation/preprocessor/has-attribute.c
@@ -6,6 +6,8 @@ __has_attribute()??? Quesako?
 #endif
 
 123 __has_attribute(nothinx) def
+#define A packed
+456 __has_attribute(A)
 
 #if __has_attribute(nothinx)
 #error "not a attribute!"
@@ -49,6 +51,7 @@ __has_attribute()??? Quesako?
 
 "has __has_attribute(), yeah!"
 123 0 def
+456 1
 "ok gcc"
 "ok gcc ignore"
 "ok sparse specific"
diff --git a/validation/preprocessor/has-builtin.c b/validation/preprocessor/has-builtin.c
index 03272fc9..010d44bd 100644
--- a/validation/preprocessor/has-builtin.c
+++ b/validation/preprocessor/has-builtin.c
@@ -28,6 +28,8 @@ constant_p
 #endif
 
 123 __has_builtin(abc) def
+#define A __builtin_constant_p
+456 __has_builtin(A)
 
 /*
  * check-name: has-builtin
@@ -39,5 +41,6 @@ constant_p
 abs
 constant_p
 123 0 def
+456 1
  * check-output-end
  */
-- 
2.47.3