linux-sparse.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] simplify parsing of storage modifiers
@ 2020-08-09 16:52 Luc Van Oostenryck
  2020-08-09 16:52 ` [PATCH 1/8] show-mod: add helper to show the modifiers but without ending space Luc Van Oostenryck
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-08-09 16:52 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

This series simplify the parsing of storage modifiers and
is part of a larger super-series aiming at rationalize the
handling of attributes and modifiers

Luc Van Oostenryck (8):
  show-mod: add helper to show the modifiers but without ending space
  show-mod: no ending space when showing a single modifier
  show-mod: no extra space when showing modifiers + ident
  parse: rework handling of storage_class
  parse: associate modifiers with their keyword
  parse: let asm_modifier() use the keyword modifier
  parse: improve error messages concerning storage specifiers
  parse: simplify set_storage_class()

 parse.c      | 237 +++++++++++++++------------------------------------
 show-parse.c |  20 ++++-
 symbol.h     |   9 +-
 3 files changed, 91 insertions(+), 175 deletions(-)


base-commit: eb6779f6f62173672b533cfbbff59758f710fb4f
-- 
2.28.0


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

* [PATCH 1/8] show-mod: add helper to show the modifiers but without ending space
  2020-08-09 16:52 [PATCH 0/8] simplify parsing of storage modifiers Luc Van Oostenryck
@ 2020-08-09 16:52 ` Luc Van Oostenryck
  2020-08-09 16:52 ` [PATCH 2/8] show-mod: no ending space when showing a single modifier Luc Van Oostenryck
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-08-09 16:52 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

modifier_string() returns either "" or a string with one or
several modifiers separated by a space. In this last case the
string has also a trailing space.

This trailing space is sometimes desired (for example when
composed with identifier name: "%s%s") but is also sometimes not
desired (for example when only the modifiers must be displayed).

So, create a variant of modifier_string() which doesn't add the
ending space: modifier_name().

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 show-parse.c | 18 +++++++++++++++++-
 symbol.h     |  1 +
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/show-parse.c b/show-parse.c
index 51a151911e3b..17a4de8be64e 100644
--- a/show-parse.c
+++ b/show-parse.c
@@ -107,7 +107,7 @@ void debug_symbol(struct symbol *sym)
  * Symbol type printout. The type system is by far the most
  * complicated part of C - everything else is trivial.
  */
-const char *modifier_string(unsigned long mod)
+static const char *show_modifiers(unsigned long mod, int term)
 {
 	static char buffer[100];
 	int len = 0;
@@ -155,10 +155,26 @@ const char *modifier_string(unsigned long mod)
 			buffer[len++] = ' ';
 		}
 	}
+	if (len && !term)		// strip the trailing space
+		--len;
 	buffer[len] = 0;
 	return buffer;
 }
 
+///
+// show the modifiers, terminated by a space if not empty
+const char *modifier_string(unsigned long mod)
+{
+	return show_modifiers(mod, 1);
+}
+
+///
+// show the modifiers, without an ending space
+const char *modifier_name(unsigned long mod)
+{
+	return show_modifiers(mod, 0);
+}
+
 static void show_struct_member(struct symbol *sym)
 {
 	printf("\t%s:%d:%ld at offset %ld.%d", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset, sym->bit_offset);
diff --git a/symbol.h b/symbol.h
index c2b60ce91c27..4792b008efe3 100644
--- a/symbol.h
+++ b/symbol.h
@@ -327,6 +327,7 @@ extern void init_linearized_builtins(int stream);
 extern void init_ctype(void);
 extern struct symbol *alloc_symbol(struct position, int type);
 extern void show_type(struct symbol *);
+extern const char *modifier_name(unsigned long mod);
 extern const char *modifier_string(unsigned long mod);
 extern void show_symbol(struct symbol *);
 extern int show_symbol_expr_init(struct symbol *sym);
-- 
2.28.0


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

* [PATCH 2/8] show-mod: no ending space when showing a single modifier
  2020-08-09 16:52 [PATCH 0/8] simplify parsing of storage modifiers Luc Van Oostenryck
  2020-08-09 16:52 ` [PATCH 1/8] show-mod: add helper to show the modifiers but without ending space Luc Van Oostenryck
@ 2020-08-09 16:52 ` Luc Van Oostenryck
  2020-08-09 16:52 ` [PATCH 3/8] show-mod: no extra space when showing modifiers + ident Luc Van Oostenryck
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-08-09 16:52 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 parse.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/parse.c b/parse.c
index cc5dbd522b3e..cc46f1a6c5a6 100644
--- a/parse.c
+++ b/parse.c
@@ -1151,7 +1151,7 @@ static struct token *attribute_aligned(struct token *token, struct symbol *attr,
 static void apply_mod(struct position *pos, unsigned long *mods, unsigned long mod)
 {
 	if (*mods & mod & ~MOD_DUP_OK)
-		warning(*pos, "duplicate %s", modifier_string(mod));
+		warning(*pos, "duplicate %s", modifier_name(mod));
 	*mods |= mod;
 }
 
-- 
2.28.0


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

* [PATCH 3/8] show-mod: no extra space when showing modifiers + ident
  2020-08-09 16:52 [PATCH 0/8] simplify parsing of storage modifiers Luc Van Oostenryck
  2020-08-09 16:52 ` [PATCH 1/8] show-mod: add helper to show the modifiers but without ending space Luc Van Oostenryck
  2020-08-09 16:52 ` [PATCH 2/8] show-mod: no ending space when showing a single modifier Luc Van Oostenryck
@ 2020-08-09 16:52 ` Luc Van Oostenryck
  2020-08-09 16:52 ` [PATCH 4/8] parse: rework handling of storage_class Luc Van Oostenryck
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-08-09 16:52 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 show-parse.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/show-parse.c b/show-parse.c
index 17a4de8be64e..0546a7b9f210 100644
--- a/show-parse.c
+++ b/show-parse.c
@@ -70,7 +70,7 @@ static void do_debug_symbol(struct symbol *sym, int indent)
 
 	if (!sym)
 		return;
-	fprintf(stderr, "%.*s%s%3d:%lu %s %s (as: %s) %p (%s:%d:%d) %s\n",
+	fprintf(stderr, "%.*s%s%3d:%lu %s%s (as: %s) %p (%s:%d:%d) %s\n",
 		indent, indent_string, typestr[sym->type],
 		sym->bit_size, sym->ctype.alignment,
 		modifier_string(sym->ctype.modifiers), show_ident(sym->ident),
-- 
2.28.0


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

* [PATCH 4/8] parse: rework handling of storage_class
  2020-08-09 16:52 [PATCH 0/8] simplify parsing of storage modifiers Luc Van Oostenryck
                   ` (2 preceding siblings ...)
  2020-08-09 16:52 ` [PATCH 3/8] show-mod: no extra space when showing modifiers + ident Luc Van Oostenryck
@ 2020-08-09 16:52 ` Luc Van Oostenryck
  2020-08-09 16:52 ` [PATCH 5/8] parse: associate modifiers with their keyword Luc Van Oostenryck
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-08-09 16:52 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

The handling of the storage class modifiers is done
differently than the other modifiers:
* they don't use MOD_... but their own enums
* consequently they can't use modifier_string() and have
  their own string table to display them.
* the attribute 'force' is considered as a kind of storage
  class. Fine, but it means that 'register' or '__tls' can't
  be used with 'force' (which is probably very fine but
  seems more as a side-effect than something really desired).

The real justification for these difference seems to be
that storage class modifiers *must* be treated differently
than the other modifiers because they don't apply at the same
level. For example, in a declaration like:
	static const int a[N];
'static' applies to the array/the whole object, while 'const'
only applies to the (type of the) elements of the array.

Storage class specifiers must thus be parsed, stored aside
and only be applied after the whole declarator have been parsed.
But other modifiers are also in the same situation (for example,
'__noreturn' or '__pure' for functions).

So, use the generic keyword/attribute handling of modifiers
for storage class specifiers but for simplicity, store them
separately in decl_state to easily do duplication tests on them.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 parse.c  | 71 ++++++++++++++++++--------------------------------------
 symbol.h |  4 +++-
 2 files changed, 25 insertions(+), 50 deletions(-)

diff --git a/parse.c b/parse.c
index cc46f1a6c5a6..2711022aba69 100644
--- a/parse.c
+++ b/parse.c
@@ -116,10 +116,6 @@ enum {
 	CInt = 0, CSInt, CUInt, CReal,
 };
 
-enum {
-	SNone = 0, STypedef, SAuto, SRegister, SExtern, SStatic, SForced, SMax,
-};
-
 static void asm_modifier(struct token *token, unsigned long *mods, unsigned long mod)
 {
 	if (*mods & mod)
@@ -1389,85 +1385,67 @@ static struct token *attribute_specifier(struct token *token, struct decl_state
 	return token;
 }
 
-static const char *storage_class[] = 
-{
-	[STypedef] = "typedef",
-	[SAuto] = "auto",
-	[SExtern] = "extern",
-	[SStatic] = "static",
-	[SRegister] = "register",
-	[SForced] = "[force]"
-};
-
 static unsigned long decl_modifiers(struct decl_state *ctx)
 {
-	static unsigned long mod[SMax] =
-	{
-		[SAuto] = MOD_AUTO,
-		[SExtern] = MOD_EXTERN,
-		[SStatic] = MOD_STATIC,
-		[SRegister] = MOD_REGISTER
-	};
 	unsigned long mods = ctx->ctype.modifiers & MOD_DECLARE;
 	ctx->ctype.modifiers &= ~MOD_DECLARE;
-	return mod[ctx->storage_class] | mods;
+	return ctx->storage_class | mods;
 }
 
-static void set_storage_class(struct position *pos, struct decl_state *ctx, int class)
+static void set_storage_class(struct position *pos, struct decl_state *ctx, unsigned long class)
 {
 	int is_tls = ctx->ctype.modifiers & MOD_TLS;
+	const char *storage = modifier_string(class);
+
 	/* __thread can be used alone, or with extern or static */
-	if (is_tls && (class != SStatic && class != SExtern)) {
+	if (is_tls && (class & ~(MOD_STATIC|MOD_EXTERN))) {
 		sparse_error(*pos, "__thread can only be used alone, or with "
 				"extern or static");
 		return;
 	}
 
-	if (!ctx->storage_class) {
+	if (!ctx->storage_class)
 		ctx->storage_class = class;
-		return;
-	}
-	if (ctx->storage_class == class)
-		sparse_error(*pos, "duplicate %s", storage_class[class]);
+	else if (ctx->storage_class == class)
+		sparse_error(*pos, "duplicate %s", storage);
 	else
 		sparse_error(*pos, "multiple storage classes");
 }
 
 static struct token *typedef_specifier(struct token *next, struct decl_state *ctx)
 {
-	set_storage_class(&next->pos, ctx, STypedef);
+	set_storage_class(&next->pos, ctx, MOD_USERTYPE);
 	return next;
 }
 
 static struct token *auto_specifier(struct token *next, struct decl_state *ctx)
 {
-	set_storage_class(&next->pos, ctx, SAuto);
+	set_storage_class(&next->pos, ctx, MOD_AUTO);
 	return next;
 }
 
 static struct token *register_specifier(struct token *next, struct decl_state *ctx)
 {
-	set_storage_class(&next->pos, ctx, SRegister);
+	set_storage_class(&next->pos, ctx, MOD_REGISTER);
 	return next;
 }
 
 static struct token *static_specifier(struct token *next, struct decl_state *ctx)
 {
-	set_storage_class(&next->pos, ctx, SStatic);
+	set_storage_class(&next->pos, ctx, MOD_STATIC);
 	return next;
 }
 
 static struct token *extern_specifier(struct token *next, struct decl_state *ctx)
 {
-	set_storage_class(&next->pos, ctx, SExtern);
+	set_storage_class(&next->pos, ctx, MOD_EXTERN);
 	return next;
 }
 
 static struct token *thread_specifier(struct token *next, struct decl_state *ctx)
 {
 	/* This GCC extension can be used alone, or with extern or static */
-	if (!ctx->storage_class || ctx->storage_class == SStatic
-			|| ctx->storage_class == SExtern) {
+	if (!(ctx->storage_class & ~(MOD_STATIC|MOD_EXTERN))) {
 		apply_qualifier(&next->pos, &ctx->ctype, MOD_TLS);
 	} else {
 		sparse_error(next->pos, "__thread can only be used alone, or "
@@ -1479,7 +1457,7 @@ static struct token *thread_specifier(struct token *next, struct decl_state *ctx
 
 static struct token *attribute_force(struct token *token, struct symbol *attr, struct decl_state *ctx)
 {
-	set_storage_class(&token->pos, ctx, SForced);
+	ctx->forced = 1;
 	return token;
 }
 
@@ -2070,14 +2048,14 @@ static struct token *parameter_declaration(struct token *token, struct symbol *s
 	sym->ctype = ctx.ctype;
 	sym->ctype.modifiers |= decl_modifiers(&ctx);
 	sym->endpos = token->pos;
-	sym->forced_arg = ctx.storage_class == SForced;
+	sym->forced_arg = ctx.forced;
 	return token;
 }
 
 struct token *typename(struct token *token, struct symbol **p, int *forced)
 {
 	struct decl_state ctx = {.prefer_abstract = 1};
-	int class;
+	unsigned long class;
 	struct symbol *sym = alloc_symbol(token->pos, SYM_NODE);
 	*p = sym;
 	token = declaration_specifiers(token, &ctx);
@@ -2086,16 +2064,11 @@ struct token *typename(struct token *token, struct symbol **p, int *forced)
 	sym->ctype = ctx.ctype;
 	sym->endpos = token->pos;
 	class = ctx.storage_class;
-	if (forced) {
-		*forced = 0;
-		if (class == SForced) {
-			*forced = 1;
-			class = 0;
-		}
-	}
+	if (forced)
+		*forced = ctx.forced;
 	if (class)
-		warning(sym->pos, "storage class in typename (%s %s)",
-			storage_class[class], show_typename(sym));
+		warning(sym->pos, "storage class in typename (%s%s)",
+			modifier_string(class), show_typename(sym));
 	return token;
 }
 
@@ -3048,7 +3021,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis
 	}
 
 	/* type define declaration? */
-	is_typedef = ctx.storage_class == STypedef;
+	is_typedef = ctx.storage_class == MOD_USERTYPE;
 
 	/* Typedefs don't have meaningful storage */
 	if (is_typedef)
diff --git a/symbol.h b/symbol.h
index 4792b008efe3..d2ca3d2ded0e 100644
--- a/symbol.h
+++ b/symbol.h
@@ -108,8 +108,10 @@ struct decl_state {
 	struct ident **ident;
 	struct symbol_op *mode;
 	unsigned long f_modifiers;		// function attributes
-	unsigned char prefer_abstract, storage_class;
+	unsigned long storage_class;
+	unsigned char prefer_abstract;
 	unsigned char autotype;
+	unsigned char forced;
 };
 
 struct pseudo;
-- 
2.28.0


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

* [PATCH 5/8] parse: associate modifiers with their keyword
  2020-08-09 16:52 [PATCH 0/8] simplify parsing of storage modifiers Luc Van Oostenryck
                   ` (3 preceding siblings ...)
  2020-08-09 16:52 ` [PATCH 4/8] parse: rework handling of storage_class Luc Van Oostenryck
@ 2020-08-09 16:52 ` Luc Van Oostenryck
  2020-08-09 16:52 ` [PATCH 6/8] parse: let asm_modifier() use the keyword modifier Luc Van Oostenryck
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-08-09 16:52 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

A significant number of declarators need to set or simply use
the modifier associated with the corresponding keyword but this
is open-coded for each of them. As result, almost all keywords
corresponding to a declaration need their own specific method.

Make this more generic by adding the associated modifier to the
ctype associated to keywords and passing the result of the keyword
lookup to the declarator methods. This way, these methods can be
made generic by getting the modifier from the ctype, like it was
already done for attributes.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 parse.c  | 156 +++++++++++++++++--------------------------------------
 symbol.h |   2 +-
 2 files changed, 48 insertions(+), 110 deletions(-)

diff --git a/parse.c b/parse.c
index 2711022aba69..37fe90c016fe 100644
--- a/parse.c
+++ b/parse.c
@@ -51,15 +51,12 @@ struct statement_list *function_computed_goto_list;
 static struct token *statement(struct token *token, struct statement **tree);
 static struct token *handle_attributes(struct token *token, struct decl_state *ctx, unsigned int keywords);
 
-typedef struct token *declarator_t(struct token *, struct decl_state *);
+typedef struct token *declarator_t(struct token *, struct symbol *, struct decl_state *);
 static declarator_t
 	struct_specifier, union_specifier, enum_specifier,
 	attribute_specifier, typeof_specifier, parse_asm_declarator,
-	typedef_specifier, inline_specifier, auto_specifier,
-	register_specifier, static_specifier, extern_specifier,
-	thread_specifier, const_qualifier, volatile_qualifier;
-static declarator_t restrict_qualifier;
-static declarator_t atomic_qualifier;
+	storage_specifier, thread_specifier;
+static declarator_t generic_qualifier;
 static declarator_t autotype_specifier;
 
 static struct token *parse_if_statement(struct token *token, struct statement *stmt);
@@ -135,19 +132,18 @@ static void asm_modifier_inline(struct token *token, unsigned long *mods)
 
 static struct symbol_op typedef_op = {
 	.type = KW_MODIFIER,
-	.declarator = typedef_specifier,
+	.declarator = storage_specifier,
 };
 
 static struct symbol_op inline_op = {
 	.type = KW_MODIFIER,
-	.declarator = inline_specifier,
+	.declarator = generic_qualifier,
 	.asm_modifier = asm_modifier_inline,
 };
 
-static declarator_t noreturn_specifier;
 static struct symbol_op noreturn_op = {
 	.type = KW_MODIFIER,
-	.declarator = noreturn_specifier,
+	.declarator = generic_qualifier,
 };
 
 static declarator_t alignas_specifier;
@@ -158,22 +154,22 @@ static struct symbol_op alignas_op = {
 
 static struct symbol_op auto_op = {
 	.type = KW_MODIFIER,
-	.declarator = auto_specifier,
+	.declarator = storage_specifier,
 };
 
 static struct symbol_op register_op = {
 	.type = KW_MODIFIER,
-	.declarator = register_specifier,
+	.declarator = storage_specifier,
 };
 
 static struct symbol_op static_op = {
 	.type = KW_MODIFIER,
-	.declarator = static_specifier,
+	.declarator = storage_specifier,
 };
 
 static struct symbol_op extern_op = {
 	.type = KW_MODIFIER,
-	.declarator = extern_specifier,
+	.declarator = storage_specifier,
 };
 
 static struct symbol_op thread_op = {
@@ -183,23 +179,23 @@ static struct symbol_op thread_op = {
 
 static struct symbol_op const_op = {
 	.type = KW_QUALIFIER,
-	.declarator = const_qualifier,
+	.declarator = generic_qualifier,
 };
 
 static struct symbol_op volatile_op = {
 	.type = KW_QUALIFIER,
-	.declarator = volatile_qualifier,
+	.declarator = generic_qualifier,
 	.asm_modifier = asm_modifier_volatile,
 };
 
 static struct symbol_op restrict_op = {
 	.type = KW_QUALIFIER,
-	.declarator = restrict_qualifier,
+	.declarator = generic_qualifier,
 };
 
 static struct symbol_op atomic_op = {
 	.type = KW_QUALIFIER,
-	.declarator = atomic_qualifier,
+	.declarator = generic_qualifier,
 };
 
 static struct symbol_op typeof_op = {
@@ -478,27 +474,27 @@ static struct init_keyword {
 #define U(I, O,...)	N("__" I,O,##__VA_ARGS__),	\
 			N("__" I "__",O,##__VA_ARGS__)
 	/* Storage classes */
-	N("auto",		&auto_op),
-	N("register",		&register_op),
-	N("static",		&static_op),
-	N("extern",		&extern_op),
+	N("auto",		&auto_op,	.mods = MOD_AUTO),
+	N("register",		&register_op,	.mods = MOD_REGISTER),
+	N("static",		&static_op,	.mods = MOD_STATIC),
+	N("extern",		&extern_op,	.mods = MOD_EXTERN),
 	N("__thread",		&thread_op),
 	N("_Thread_local",	&thread_op),
 
-	A("inline",		&inline_op),
+	A("inline",		&inline_op,	.mods = MOD_INLINE),
 
 	/* Typedef ... */
-	N("typedef",		&typedef_op),
+	N("typedef",		&typedef_op,	.mods = MOD_USERTYPE),
 	A("typeof",		&typeof_op),
 	N("__auto_type",	&autotype_op),
 
 	/* Type qualifiers */
-	A("const",		&const_op),
-	A("volatile",		&volatile_op),
-	A("restrict",		&restrict_op),
+	A("const",		&const_op,	.mods = MOD_CONST),
+	A("volatile",		&volatile_op,	.mods = MOD_VOLATILE),
+	A("restrict",		&restrict_op,	.mods = MOD_RESTRICT),
 
-	N("_Atomic",		&atomic_op),
-	N("_Noreturn",		&noreturn_op),
+	N("_Atomic",		&atomic_op,	.mods = MOD_ATOMIC),
+	N("_Noreturn",		&noreturn_op,	.mods = MOD_NORETURN),
 	N("_Alignas",		&alignas_op),
 
 	U("attribute",		&attribute_op),
@@ -826,12 +822,12 @@ static struct token *parse_union_declaration(struct token *token, struct symbol
 	return struct_declaration_list(token, &sym->symbol_list);
 }
 
-static struct token *struct_specifier(struct token *token, struct decl_state *ctx)
+static struct token *struct_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx)
 {
 	return struct_union_enum_specifier(SYM_STRUCT, token, ctx, parse_struct_declaration);
 }
 
-static struct token *union_specifier(struct token *token, struct decl_state *ctx)
+static struct token *union_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx)
 {
 	return struct_union_enum_specifier(SYM_UNION, token, ctx, parse_union_declaration);
 }
@@ -1065,7 +1061,7 @@ static struct token *parse_enum_declaration(struct token *token, struct symbol *
 	return token;
 }
 
-static struct token *enum_specifier(struct token *token, struct decl_state *ctx)
+static struct token *enum_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx)
 {
 	struct token *ret = struct_union_enum_specifier(SYM_ENUM, token, ctx, parse_enum_declaration);
 	struct ctype *ctype = &ctx->ctype.base_type->ctype;
@@ -1078,15 +1074,15 @@ static struct token *enum_specifier(struct token *token, struct decl_state *ctx)
 
 static void apply_ctype(struct position pos, struct ctype *thistype, struct ctype *ctype);
 
-static struct token *typeof_specifier(struct token *token, struct decl_state *ctx)
+static struct token *typeof_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx)
 {
-	struct symbol *sym;
 
 	if (!match_op(token, '(')) {
 		sparse_error(token->pos, "expected '(' after typeof");
 		return token;
 	}
 	if (lookup_type(token->next)) {
+		struct symbol *sym;
 		token = typename(token->next, &sym, NULL);
 		ctx->ctype.base_type = sym->ctype.base_type;
 		apply_ctype(token->pos, &sym->ctype, &ctx->ctype);
@@ -1104,7 +1100,7 @@ static struct token *typeof_specifier(struct token *token, struct decl_state *ct
 	return expect(token, ')', "after typeof");
 }
 
-static struct token *autotype_specifier(struct token *token, struct decl_state *ctx)
+static struct token *autotype_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx)
 {
 	ctx->ctype.base_type = &autotype_ctype;
 	ctx->autotype = 1;
@@ -1158,7 +1154,7 @@ static void apply_qualifier(struct position *pos, struct ctype *ctx, unsigned lo
 
 static struct token *attribute_modifier(struct token *token, struct symbol *attr, struct decl_state *ctx)
 {
-	apply_qualifier(&token->pos, &ctx->ctype, attr->ctype.modifiers);
+	apply_mod(&token->pos, &ctx->ctype.modifiers, attr->ctype.modifiers);
 	return token;
 }
 
@@ -1353,7 +1349,7 @@ static struct token *recover_unknown_attribute(struct token *token)
 	return token;
 }
 
-static struct token *attribute_specifier(struct token *token, struct decl_state *ctx)
+static struct token *attribute_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx)
 {
 	token = expect(token, '(', "after attribute");
 	token = expect(token, '(', "after attribute");
@@ -1392,57 +1388,29 @@ static unsigned long decl_modifiers(struct decl_state *ctx)
 	return ctx->storage_class | mods;
 }
 
-static void set_storage_class(struct position *pos, struct decl_state *ctx, unsigned long class)
+static struct token *storage_specifier(struct token *next, struct symbol *sym, struct decl_state *ctx)
 {
 	int is_tls = ctx->ctype.modifiers & MOD_TLS;
+	unsigned long class = sym->ctype.modifiers;
 	const char *storage = modifier_string(class);
 
 	/* __thread can be used alone, or with extern or static */
 	if (is_tls && (class & ~(MOD_STATIC|MOD_EXTERN))) {
-		sparse_error(*pos, "__thread can only be used alone, or with "
+		sparse_error(next->pos, "__thread can only be used alone, or with "
 				"extern or static");
-		return;
+		return next;
 	}
 
 	if (!ctx->storage_class)
 		ctx->storage_class = class;
 	else if (ctx->storage_class == class)
-		sparse_error(*pos, "duplicate %s", storage);
+		sparse_error(next->pos, "duplicate %s", storage);
 	else
-		sparse_error(*pos, "multiple storage classes");
-}
-
-static struct token *typedef_specifier(struct token *next, struct decl_state *ctx)
-{
-	set_storage_class(&next->pos, ctx, MOD_USERTYPE);
-	return next;
-}
-
-static struct token *auto_specifier(struct token *next, struct decl_state *ctx)
-{
-	set_storage_class(&next->pos, ctx, MOD_AUTO);
-	return next;
-}
-
-static struct token *register_specifier(struct token *next, struct decl_state *ctx)
-{
-	set_storage_class(&next->pos, ctx, MOD_REGISTER);
-	return next;
-}
-
-static struct token *static_specifier(struct token *next, struct decl_state *ctx)
-{
-	set_storage_class(&next->pos, ctx, MOD_STATIC);
-	return next;
-}
-
-static struct token *extern_specifier(struct token *next, struct decl_state *ctx)
-{
-	set_storage_class(&next->pos, ctx, MOD_EXTERN);
+		sparse_error(next->pos, "multiple storage classes");
 	return next;
 }
 
-static struct token *thread_specifier(struct token *next, struct decl_state *ctx)
+static struct token *thread_specifier(struct token *next, struct symbol *sym, struct decl_state *ctx)
 {
 	/* This GCC extension can be used alone, or with extern or static */
 	if (!(ctx->storage_class & ~(MOD_STATIC|MOD_EXTERN))) {
@@ -1461,19 +1429,7 @@ static struct token *attribute_force(struct token *token, struct symbol *attr, s
 	return token;
 }
 
-static struct token *inline_specifier(struct token *next, struct decl_state *ctx)
-{
-	apply_qualifier(&next->pos, &ctx->ctype, MOD_INLINE);
-	return next;
-}
-
-static struct token *noreturn_specifier(struct token *next, struct decl_state *ctx)
-{
-	apply_qualifier(&next->pos, &ctx->ctype, MOD_NORETURN);
-	return next;
-}
-
-static struct token *alignas_specifier(struct token *token, struct decl_state *ctx)
+static struct token *alignas_specifier(struct token *token, struct symbol *sym, struct decl_state *ctx)
 {
 	int alignment = 0;
 
@@ -1508,27 +1464,9 @@ static struct token *alignas_specifier(struct token *token, struct decl_state *c
 	return token;
 }
 
-static struct token *const_qualifier(struct token *next, struct decl_state *ctx)
-{
-	apply_qualifier(&next->pos, &ctx->ctype, MOD_CONST);
-	return next;
-}
-
-static struct token *volatile_qualifier(struct token *next, struct decl_state *ctx)
-{
-	apply_qualifier(&next->pos, &ctx->ctype, MOD_VOLATILE);
-	return next;
-}
-
-static struct token *restrict_qualifier(struct token *next, struct decl_state *ctx)
-{
-	apply_qualifier(&next->pos, &ctx->ctype, MOD_RESTRICT);
-	return next;
-}
-
-static struct token *atomic_qualifier(struct token *next, struct decl_state *ctx)
+static struct token *generic_qualifier(struct token *next, struct symbol *sym, struct decl_state *ctx)
 {
-	apply_qualifier(&next->pos, &ctx->ctype, MOD_ATOMIC);
+	apply_qualifier(&next->pos, &ctx->ctype, sym->ctype.modifiers);
 	return next;
 }
 
@@ -1615,7 +1553,7 @@ static struct token *handle_qualifiers(struct token *t, struct decl_state *ctx)
 			break;
 		t = t->next;
 		if (s->op->declarator)
-			t = s->op->declarator(t, ctx);
+			t = s->op->declarator(t, s, ctx);
 	}
 	return t;
 }
@@ -1667,7 +1605,7 @@ static struct token *declaration_specifiers(struct token *token, struct decl_sta
 		}
 		token = token->next;
 		if (s->op->declarator)	// Note: this eats attributes
-			token = s->op->declarator(token, ctx);
+			token = s->op->declarator(token, s, ctx);
 		if (s->op->type & KW_EXACT) {
 			ctx->ctype.base_type = s->ctype.base_type;
 			ctx->ctype.modifiers |= s->ctype.modifiers;
@@ -1791,7 +1729,7 @@ static struct token *handle_attributes(struct token *token, struct decl_state *c
 			break;
 		if (!(keyword->op->type & keywords))
 			break;
-		token = keyword->op->declarator(token->next, ctx);
+		token = keyword->op->declarator(token->next, keyword, ctx);
 		keywords &= KW_ATTRIBUTE;
 	}
 	return token;
@@ -2157,7 +2095,7 @@ static struct token *parse_asm_statement(struct token *token, struct statement *
 	return expect(token, ';', "at end of asm-statement");
 }
 
-static struct token *parse_asm_declarator(struct token *token, struct decl_state *ctx)
+static struct token *parse_asm_declarator(struct token *token, struct symbol *sym, struct decl_state *ctx)
 {
 	struct expression *expr;
 	token = expect(token, '(', "after asm");
diff --git a/symbol.h b/symbol.h
index d2ca3d2ded0e..657a6e0fb354 100644
--- a/symbol.h
+++ b/symbol.h
@@ -126,7 +126,7 @@ struct symbol_op {
 	struct pseudo *(*linearize)(struct entrypoint *, struct expression *);
 
 	/* keywords */
-	struct token *(*declarator)(struct token *token, struct decl_state *ctx);
+	struct token *(*declarator)(struct token *token, struct symbol *, struct decl_state *ctx);
 	struct token *(*statement)(struct token *token, struct statement *stmt);
 	struct token *(*toplevel)(struct token *token, struct symbol_list **list);
 	struct token *(*attribute)(struct token *token, struct symbol *attr, struct decl_state *ctx);
-- 
2.28.0


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

* [PATCH 6/8] parse: let asm_modifier() use the keyword modifier
  2020-08-09 16:52 [PATCH 0/8] simplify parsing of storage modifiers Luc Van Oostenryck
                   ` (4 preceding siblings ...)
  2020-08-09 16:52 ` [PATCH 5/8] parse: associate modifiers with their keyword Luc Van Oostenryck
@ 2020-08-09 16:52 ` Luc Van Oostenryck
  2020-08-09 16:52 ` [PATCH 7/8] parse: improve error messages concerning storage specifiers Luc Van Oostenryck
  2020-08-09 16:52 ` [PATCH 8/8] parse: simplify set_storage_class() Luc Van Oostenryck
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-08-09 16:52 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Now that 'MOD_INLINE' & 'MOD_VOLATILE' are associated with their
corresponding keyword, a single asm_modifier() method can cover
both cases.

So, replace asm_modifier_inline() & asm_modifier_volatile() by
a single, generic version: asm_modifier().

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 parse.c  | 16 +++-------------
 symbol.h |  2 +-
 2 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/parse.c b/parse.c
index 37fe90c016fe..fad41d36dda6 100644
--- a/parse.c
+++ b/parse.c
@@ -120,16 +120,6 @@ static void asm_modifier(struct token *token, unsigned long *mods, unsigned long
 	*mods |= mod;
 }
 
-static void asm_modifier_volatile(struct token *token, unsigned long *mods)
-{
-	asm_modifier(token, mods, MOD_VOLATILE);
-}
-
-static void asm_modifier_inline(struct token *token, unsigned long *mods)
-{
-	asm_modifier(token, mods, MOD_INLINE);
-}
-
 static struct symbol_op typedef_op = {
 	.type = KW_MODIFIER,
 	.declarator = storage_specifier,
@@ -138,7 +128,7 @@ static struct symbol_op typedef_op = {
 static struct symbol_op inline_op = {
 	.type = KW_MODIFIER,
 	.declarator = generic_qualifier,
-	.asm_modifier = asm_modifier_inline,
+	.asm_modifier = asm_modifier,
 };
 
 static struct symbol_op noreturn_op = {
@@ -185,7 +175,7 @@ static struct symbol_op const_op = {
 static struct symbol_op volatile_op = {
 	.type = KW_QUALIFIER,
 	.declarator = generic_qualifier,
-	.asm_modifier = asm_modifier_volatile,
+	.asm_modifier = asm_modifier,
 };
 
 static struct symbol_op restrict_op = {
@@ -2076,7 +2066,7 @@ static struct token *parse_asm_statement(struct token *token, struct statement *
 	while (token_type(token) == TOKEN_IDENT) {
 		struct symbol *s = lookup_keyword(token->ident, NS_TYPEDEF);
 		if (s && s->op  && s->op->asm_modifier)
-			s->op->asm_modifier(token, &mods);
+			s->op->asm_modifier(token, &mods, s->ctype.modifiers);
 		else if (token->ident == &goto_ident)
 			asm_modifier(token, &mods, MOD_ASM_GOTO);
 		token = token->next;
diff --git a/symbol.h b/symbol.h
index 657a6e0fb354..4f9dd7417cc3 100644
--- a/symbol.h
+++ b/symbol.h
@@ -131,7 +131,7 @@ struct symbol_op {
 	struct token *(*toplevel)(struct token *token, struct symbol_list **list);
 	struct token *(*attribute)(struct token *token, struct symbol *attr, struct decl_state *ctx);
 	struct symbol *(*to_mode)(struct symbol *);
-	void          (*asm_modifier)(struct token *token, unsigned long *mods);
+	void (*asm_modifier)(struct token *token, unsigned long *mods, unsigned long mod);
 
 	int test, set, class;
 };
-- 
2.28.0


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

* [PATCH 7/8] parse: improve error messages concerning storage specifiers
  2020-08-09 16:52 [PATCH 0/8] simplify parsing of storage modifiers Luc Van Oostenryck
                   ` (5 preceding siblings ...)
  2020-08-09 16:52 ` [PATCH 6/8] parse: let asm_modifier() use the keyword modifier Luc Van Oostenryck
@ 2020-08-09 16:52 ` Luc Van Oostenryck
  2020-08-09 16:52 ` [PATCH 8/8] parse: simplify set_storage_class() Luc Van Oostenryck
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-08-09 16:52 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 parse.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/parse.c b/parse.c
index fad41d36dda6..92ca1b66e140 100644
--- a/parse.c
+++ b/parse.c
@@ -1382,12 +1382,11 @@ static struct token *storage_specifier(struct token *next, struct symbol *sym, s
 {
 	int is_tls = ctx->ctype.modifiers & MOD_TLS;
 	unsigned long class = sym->ctype.modifiers;
-	const char *storage = modifier_string(class);
+	const char *storage = modifier_name(class);
 
 	/* __thread can be used alone, or with extern or static */
 	if (is_tls && (class & ~(MOD_STATIC|MOD_EXTERN))) {
-		sparse_error(next->pos, "__thread can only be used alone, or with "
-				"extern or static");
+		sparse_error(next->pos, "__thread cannot be used with '%s'", storage);
 		return next;
 	}
 
@@ -1406,8 +1405,8 @@ static struct token *thread_specifier(struct token *next, struct symbol *sym, st
 	if (!(ctx->storage_class & ~(MOD_STATIC|MOD_EXTERN))) {
 		apply_qualifier(&next->pos, &ctx->ctype, MOD_TLS);
 	} else {
-		sparse_error(next->pos, "__thread can only be used alone, or "
-				"with extern or static");
+		sparse_error(next->pos, "__thread cannot be used with '%s'",
+			modifier_name(ctx->storage_class));
 	}
 
 	return next;
-- 
2.28.0


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

* [PATCH 8/8] parse: simplify set_storage_class()
  2020-08-09 16:52 [PATCH 0/8] simplify parsing of storage modifiers Luc Van Oostenryck
                   ` (6 preceding siblings ...)
  2020-08-09 16:52 ` [PATCH 7/8] parse: improve error messages concerning storage specifiers Luc Van Oostenryck
@ 2020-08-09 16:52 ` Luc Van Oostenryck
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-08-09 16:52 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

The second test is now made as the else part of the first test,
saving a 'return' that is otherwise not needed.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 parse.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/parse.c b/parse.c
index 92ca1b66e140..f3f33790eac0 100644
--- a/parse.c
+++ b/parse.c
@@ -1385,12 +1385,9 @@ static struct token *storage_specifier(struct token *next, struct symbol *sym, s
 	const char *storage = modifier_name(class);
 
 	/* __thread can be used alone, or with extern or static */
-	if (is_tls && (class & ~(MOD_STATIC|MOD_EXTERN))) {
+	if (is_tls && (class & ~(MOD_STATIC|MOD_EXTERN)))
 		sparse_error(next->pos, "__thread cannot be used with '%s'", storage);
-		return next;
-	}
-
-	if (!ctx->storage_class)
+	else if (!ctx->storage_class)
 		ctx->storage_class = class;
 	else if (ctx->storage_class == class)
 		sparse_error(next->pos, "duplicate %s", storage);
-- 
2.28.0


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

end of thread, other threads:[~2020-08-09 16:52 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-09 16:52 [PATCH 0/8] simplify parsing of storage modifiers Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 1/8] show-mod: add helper to show the modifiers but without ending space Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 2/8] show-mod: no ending space when showing a single modifier Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 3/8] show-mod: no extra space when showing modifiers + ident Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 4/8] parse: rework handling of storage_class Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 5/8] parse: associate modifiers with their keyword Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 6/8] parse: let asm_modifier() use the keyword modifier Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 7/8] parse: improve error messages concerning storage specifiers Luc Van Oostenryck
2020-08-09 16:52 ` [PATCH 8/8] parse: simplify set_storage_class() Luc Van Oostenryck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).